Dalam bash, apakah mungkin untuk menggunakan variabel integer dalam kontrol loop dari for for?


65

Saya memiliki skrip bash berikut:

#!/bin/bash

upperlim=10

for i in {0..10}
do
echo $i
done

for i in {0..$upperlim}
do
echo $i
done

forLoop pertama ( tanpa variabel upperlimdalam kontrol loop) berfungsi dengan baik, tetapi forloop kedua ( dengan variabel upperlimdalam kontrol loop) tidak. Apakah ada cara saya bisa memodifikasi forloop kedua sehingga berfungsi? Terima kasih atas waktunya.


4
hm, bahkan for i in {0..$((upperlim))}; do echo $i; donetidak berfungsi
Bonsi Scott

dan +1 karena menurut saya perilaku itu menarik
Bonsi Scott


Tautan eksternal yang menjawab ini: cyberciti.biz/faq/…
kon psych

Jawaban:


62

Alasan untuk ini adalah urutan di mana hal-hal terjadi di bash. Ekspansi brace terjadi sebelum variabel diperluas. Untuk mencapai tujuan Anda, Anda perlu menggunakan C-style untuk loop:

upperlim=10

for ((i=0; i<=upperlim; i++)); do
   echo "$i"
done

1
Dan berfungsi zshjuga (tetapi tidak untuk csh, tcsh).
matematika

29

Untuk menyelesaikan ini dalam gaya Anda menggunakan apa-apa selain built-in Anda harus menggunakan eval:

d=12

for i in `eval echo {0..$d}`
do
echo $i
done

Tetapi dengan seq:

lowerlimit=0
upperlimit=12

for i in $(seq $lowerlimit $upperlimit)
do
echo $i
done

Secara pribadi saya menemukan penggunaan seqmenjadi lebih mudah dibaca.


Untuk "bawaan"? seqadalah perintah eksternal dan tidak tersedia di mana-mana bash.
jordanm

9
@jordanm: Untuk menggunakan semua bawaan dengan bash. Lalu saya berkata "tetapi dengan seq", mengakui bahwa itu bukan bawaan.
Jodie C

Fakta bahwa ekspansi brace dibangun bukanlah masalah di sini. readadalah builtin misalnya, tetapi tidak ada alasan untuk evalitu.
jordanm

1
Builtin tidak bermasalah sama sekali. Saya ingin memberikan solusi all-bash untuk penanya. Jika Anda ingin terus berdebat tentang ini, bawa ke obrolan; komentar tidak baik untuk hal semacam ini
Jodie C

8

Cara POSIX

Jika Anda peduli tentang portabilitas, gunakan contoh dari standar POSIX :

i=2
END=5
while [ $i -le $END ]; do
    echo $i
    i=$(($i+1))
done

Keluaran:

2
3
4
5

Hal-hal yang bukan POSIX:


1

Pendekatan Anda tidak akan berfungsi karena ekspansi bash brace terjadi sebelum ekspansi parameter. Anda perlu memperluas variabel sebelum.

Anda dapat bekerja dengan eval :

upperlim=10
eval '
        for i in {0..'"$upperlim"'}
        do
                echo $i
        done
'

Dengan Loop Sementara :

upperlim=10
#with while
start=0
while [[ $start -le $upperlim ]]
do
    echo "$start"
    ((start = start + 1))
done

Anda juga dapat melakukannya dengan perintah seq :

upperlim=10
#seq
for i in $(seq "$upperlim"); do
  echo "$i"
done

Jika Anda ingin menjalankannya, for i in {0..$upperlim}Anda harus menggunakan kornshell. misalnya:

#!/bin/ksh
upperlim=10

for i in {0..$upperlim}
do
        echo $i
done
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.