Trong bash, có thể sử dụng một biến số nguyên trong điều khiển vòng lặp của vòng lặp for không?


65

Tôi có tập lệnh bash sau:

#!/bin/bash

upperlim=10

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

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

forVòng lặp đầu tiên ( không có biến upperlimtrong điều khiển vòng lặp) hoạt động tốt, nhưng forvòng lặp thứ hai ( với biến upperlimtrong điều khiển vòng lặp) thì không. Có cách nào để tôi có thể sửa đổi forvòng lặp thứ hai để nó hoạt động không? Cảm ơn vì đã dành thời gian cho tôi.


4
hm, thậm chí for i in {0..$((upperlim))}; do echo $i; donekhông hoạt động
Bonsi Scott

và +1 vì tôi thấy hành vi đó thú vị
Bonsi Scott

trang web chéo có thể trùng lặp của: stackoverflow.com/questions/169511/ từ
Ciro Santilli 心 心 事件

Một liên kết bên ngoài trả lời điều này: cyberciti.biz/faq/ từ
kon psych

Câu trả lời:


62

Lý do cho điều này là thứ tự trong đó mọi thứ xảy ra trong bash. Mở rộng cú đúp xảy ra trước khi các biến được mở rộng. Để hoàn thành mục tiêu của mình, bạn cần sử dụng kiểu C cho vòng lặp:

upperlim=10

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

1
Và làm việc zshlà tốt (nhưng không phải cho csh, tcsh).
toán

29

Để hoàn thành điều này theo phong cách của bạn, không cần sử dụng gì ngoài việc tích hợp, bạn phải sử dụng eval:

d=12

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

Nhưng với seq:

lowerlimit=0
upperlimit=12

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

Cá nhân tôi thấy việc sử dụng seqđể dễ đọc hơn.


Cho "tích hợp"? seqlà một lệnh bên ngoài và không có sẵn ở mọi nơi bash.
jordanm

9
@jordanm: Để sử dụng tất cả các nội trang với bash. Sau đó, tôi nói "nhưng với seq", thừa nhận rằng đó không phải là một tích hợp.
Jodie C

Thực tế là mở rộng cú đúp được xây dựng không phải là vấn đề ở đây. readlà một ví dụ dựng sẵn, nhưng không có lý do gì cho evalnó.
jordanm

1
Nội dung không có vấn đề gì cả. Tôi muốn cung cấp một giải pháp bash cho người hỏi. Nếu bạn muốn tiếp tục tranh luận về điều này, hãy mang nó đi trò chuyện; ý kiến ​​không tốt cho loại điều này
Jodie C

8

Cách POSIX

Nếu bạn quan tâm đến tính di động, hãy sử dụng ví dụ từ tiêu chuẩn POSIX :

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

Đầu ra:

2
3
4
5

Những thứ không phải là POSIX:


1

Cách tiếp cận của bạn sẽ không hoạt động vì trong bash brace-bung xảy ra trước khi mở rộng tham số. Bạn cần mở rộng biến trước.

Bạn có thể làm việc với eval :

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

Với vòng lặp While :

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

Ngoài ra, bạn có thể làm điều đó với lệnh seq :

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

Nếu bạn muốn chạy với for i in {0..$upperlim}bạn sẽ cần phải sử dụng kornshell. ví dụ:

#!/bin/ksh
upperlim=10

for i in {0..$upperlim}
do
        echo $i
done
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.