2011-02-10 32 views
6

Tôi đang gặp sự cố với chuỗi được tạo sẵn (ví dụ: không sử dụng seq) trong Bash khi số seq là một biến. Ví dụ, công trình này và in tôi 1 2 3:Mở rộng chuỗi và biến trong bash

for i in {1..3};do echo $i;done 

nhưng điều này:

bash-3.2 $ a = 3; for i in {1 .. $ a}; làm $ echo i; thực hiện

thất bại và in tôi {1..3} chỉ

này làm việc với ZSH và tôi biết tôi có một sự thay thế để thực hiện một điều ngược nhưng tự hỏi nếu điều này là một lỗi hoặc một cú đúp tính năng mở rộng!

+1

thể trùng lặp của [Lập luận truyền vào vòng lặp for trong kịch bản bash] (http://stackoverflow.com/ câu hỏi/4764383/arguments-pass-in-for-loop-in-bash-script) –

Trả lời

4

Trong Bash, mở rộng cú đúp được thực hiện trước khi mở rộng biến. Xem Shell Expansions cho đơn đặt hàng.

$ a=7; echo {1..3} {4..$a} 
1 2 3 {4..7} 

Nếu bạn muốn sử dụng biến, hãy sử dụng vòng lặp C theo kiểu for như trong câu trả lời của Shawn.

3
$ num=3 
$ for i in $(eval echo {1..$num});do echo $i;done 
1 
2 
3 
+0

trông giống như loại hack cho tôi ... nhưng cảm ơn .. –

+0

Ít hiệu quả hơn vòng lặp kiểu C (do sử dụng một subshell) và mang một nguy cơ bảo mật: không sử dụng 'eval' trừ khi bạn hoàn toàn kiểm soát hoặc đã xác nhận giá trị của các biến được sử dụng trong chuỗi được chuyển đến' eval'. Nếu không, các lệnh tùy ý có thể được thực thi. Ví dụ: giá trị '$ num' được tạo cẩn thận sau sẽ liệt kê các tệp trong thư mục chính của người dùng hiện tại: ' num = '}; ls ~; {'; cho tôi trong $ (eval echo {1 .. $ num}); echo $ i; done' – mklement0

4

Một thay thế sẽ được sử dụng các cấu trúc kép ngoặc cho phép C-style bẹ:

A=3 
for ((i=1; i<=$A; i++)); do 
    echo $i 
done 
+0

Xin chào, tôi không quan tâm đến việc sử dụng lệnh bên ngoài mà nội bộ bash được xây dựng. –

+0

anh ta không muốn sử dụng 'seq' – kurumi

+0

Xin lỗi, bỏ lỡ điều đó. Đã cập nhật câu trả lời. –

1

tùy chọn khác là sử dụng lệnh seq:

a=3; for i in $(seq 1 $a);do echo $i;done 
+0

Không hiệu quả do sử dụng một tiện ích bên ngoài, nhưng nó đơn giản và nó hoạt động. – mklement0

-1

thử điều này:

$ start=3 
$ end=5 
$ echo {$(echo $start)..$(echo $end)} 
+1

Điều đó in sau _literal_: '{3..5}', rõ ràng không phải là ý định. Nếu bạn theo liên kết trong câu trả lời được chấp nhận, bạn sẽ thấy rằng việc mở rộng cú đúp ('{...}') xảy ra _before_ lệnh thay thế ('$ (...)'), đó là lý do tại sao cách tiếp cận của bạn không thể làm việc (trong _Bash_, như được gắn thẻ, nó _would_ làm việc trong Ksh và Zsh, nhưng ở đó bạn có thể sử dụng các biến _directly_ trong các dấu ngoặc mở rộng, vì vậy bạn chỉ sử dụng 'start = 3 end = 5; echo {$ start .. $ end}') . – mklement0

+0

xin lỗi, tôi đã nhầm lẫn, echo {$ (echo $ start) .. $ (echo $ end)} không hoạt động, nhưng {$ start, $ end} kết quả đầu ra "3 5". –

+0

Có, nó có, nhưng đó là hình thức mở rộng cú đúp _list_ (',' các mục khác nhau), trong khi những gì OP đang tìm kiếm là dạng _sequence_ (range) ('..'). Theo thuật ngữ cụ thể: không phải '3 5' là kết quả mong muốn, nhưng' 3 4 5'. – mklement0

0

Tôi cũng cần thiết để làm somenthing như:

n = số số; {1 .. $ n..increment}

vì vậy tôi sử dụng workaround này:

n=100 
i=1 
while [ $i -lt $n ] 
do 
echo $i 
i=$(($i+1)) 
done 
Các vấn đề liên quan