2014-04-18 19 views
13

Làm cách nào để sửa đổi mã sau để khi chạy trong zsh, nó mở rộng $things và lặp lại từng từ một?Làm cách nào để lặp qua chuỗi một từ tại một thời điểm trong zsh

things="one two" 

for one_thing in $things; do 
    echo $one_thing 
done 

Tôi muốn đầu ra là:

one 
two 

Nhưng khi viết ở trên, nó kết quả đầu ra:

one two 

(Tôi đang tìm kiếm các hành vi mà bạn nhận được khi chạy trên mã trong bash)

+1

Điều đó có nghĩa là 'zsh' không phải là từ tách' $ things' khi nó là danh sách của một vòng lặp 'for'? Liệu nó có xâm nhập vào vòng lặp chỉ một lần không? Trả lời, sau khi chiến đấu thông qua kịch bản cấu hình, là "Có". Scratch 'zsh' từ danh sách các shell có thể sử dụng được; đó là quá non-POSIX-shell như thế nào. Tôi thậm chí không thể bận tâm để bắt đầu suy nghĩ về cách nó có thể được cấu hình để làm việc 'bình thường'. –

Trả lời

23

Để xem hành vi tương thích với vỏ Bourne, bạn cần đặt tùy chọn SH_WORD_SPLIT:

setopt shwordsplit  # this can be unset by saying: unsetopt shwordsplit 
things="one two" 

for one_thing in $things; do 
    echo $one_thing 
done 

sẽ tạo ra:

one 
two 

Tuy nhiên, nó được khuyến khích sử dụng một mảng cho sản xuất tách từ, ví dụ:

things=(one two) 

for one_thing in $things; do 
    echo $one_thing 
done 

Bạn cũng có thể muốn tham khảo đến:

3.1: Why does $var where var="foo bar" not do what I expect?

+0

Thay vì đặt 'shwordsplit' trên toàn cầu, bạn có thể bật tách từ kiểu' sh' (sử dụng 'IFS', tất nhiên) cho một tham số duy nhất với' $ {= things} '. – chepner

+0

@chepner, trông như thế nào? Tôi đã thử 'IFS = ''; cho one_thing trong $ {= things}; do' nhưng có lỗi 'bad replace' –

+0

@RobBednark Tại sao bạn không sử dụng mảng? – devnull

4

Bạn có thể sử dụng z cờ mở rộng biến để làm tách chữ trên một biến

things="one two" 

for one_thing in ${(z)things}; do 
    echo $one_thing 
done 

Đọc thêm về vấn đề này và cờ biến khác trong man zshexpn, dưới "Flags Expansion Parameter."

-1

Bạn có thể giả sử Bộ tách trường nội bộ (IFS) trên bash thành \ x20 (dấu cách). Điều này làm cho công việc sau:

#IFS=$'\x20' 
#things=(one two) #array 
things="one two" #string version 

for thing in ${things[@]} 
do 
    echo $thing 
done 

Với điều này, bạn có thể thực hiện điều này theo nhiều cách khác nhau, chỉ cần thao tác IFS; ngay cả trên các chuỗi nhiều dòng.

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