2015-09-25 12 views
5

Tôi muốn làm điều gì đó như thế này:Bash cho vòng lặp với các không gian

COMMANDS='"ls /" "df ~" "du -hs ~/Devel/"' 
for i in $COMMANDS; do 
    echo $i 
done 

đâu kết quả sẽ là:

ls/
df ~ 
du -hs ~/Devel/ 

Nhưng tôi không thể tìm thấy đúng cú pháp cho các không gian.

Trả lời

8
COMMANDS=("ls /" "df ~" "du -hs ~/Devel/") 
for i in "${COMMANDS[@]}"; do 
    echo "$i" 
done 

Điều này sử dụng mảng để lưu trữ lệnh. Tính năng này cũng có sẵn trong ksh, zsh, nhưng không có trong sh.

Mảng hoạt động giống như mảng đối số "[email protected]". Áp dụng một vòng lặp for trên "${ARRAY_NAME[@]}" (các dấu ngoặc kép là quan trọng) sẽ cung cấp cho bạn từng hạng mục liên tiếp. Nếu bạn bỏ qua các dấu ngoặc kép, tất cả sẽ được trộn lẫn với nhau và phân tách trên các dấu phân tách có trong biến môi trường IFS của bạn ('\t', '\n'' ' theo mặc định).

+0

Đây là câu trả lời đúng cho câu hỏi cụ thể được hỏi, nhưng như chepner đã chỉ ra, đó là một bước chính xác xuống đường dẫn sai. –

+0

@GordonDavisson Một số người nghĩ về việc họ có thể hay không trong khi những người khác nghĩ về việc họ có nên hay không. Tôi có xu hướng là loại đầu tiên. : D – PSkocik

5

Tôi khuyên bạn không nên làm điều đó chút nào. Thứ nhất, nó dài hơn và phức tạp hơn nhiều so với việc chỉ cần viết

ls/
df ~ 
du -hs ~/Devel/ 

Thứ hai, các chuỗi phẳng không thể lưu trữ các chuỗi được phân cách bằng dấu cách, không gian. Không có cách nào (và có, tôi bỏ qua eval) để phân biệt giữa các khoảng trống tách biệt các lệnh và khoảng trắng tách các đối số trong một lệnh. Bạn có thể sử dụng một mảng cho lệnh đơn giản, nhưng bạn không thể lồng mảng, vì vậy ngay sau khi đối số cho một trong các lệnh của bạn chứa dấu cách, bạn sẽ quay lại vấn đề ban đầu.

commands=("ls /" "df ~" "du -hs ~/Devel") # OK, but... 
commands=("ls \"foo bar\"" "echo 'hello world'") # No. 

Nếu bạn muốn tập lệnh của bạn có thể chạy các tệp tùy ý được chỉ định thay thế (nghĩa là, triển khai hệ thống trình cắm).

command_dir=~/myscript_plugins 
for f in "$command_dir"; do 
    source "$f" 
done 

nơi một tệp cho mỗi lệnh bạn muốn chạy.

Hoặc, xác định một loạt các chức năng, và lưu trữ tên của họ trong một chuỗi (tên hàm không thể chứa khoảng trắng, vì vậy không cần cho mảng):

lister() { ls /; } 
dfer() { df ~; } 
duer() { du -hs ~/Devel; } 

commands="lister dfer duer" 
for command in $commands; do 
    $command 
done 

hoặc

commands=(lister dfer duer) 
for command in "${commands[@]}"; do 
    $command 
done 

Đọc thêm: I'm trying to put a command in a variable, but the complex cases always fail!

+0

Tôi biết câu trả lời của bạn chính xác hơn, nhưng tôi đánh dấu câu trả lời khác vì nó đơn giản hơn và đủ trong hầu hết các trường hợp. Cảm ơn mặc dù! – dargaud

Các vấn đề liên quan