2013-10-24 13 views
46

Bash cho phép sử dụng: cat <(echo "$FILECONTENT")Làm thế nào để ống đầu vào cho một Bash vòng lặp while và giữ gìn các biến sau khi vòng lặp kết thúc

Bash cũng cho phép sử dụng: while read i; do echo $i; done </etc/passwd

kết hợp trước hai điều này có thể được sử dụng: echo $FILECONTENT | while read i; do echo $i; done

Vấn đề cuối cùng là nó tạo ra sub-shell và sau khi vòng lặp while kết thúc biến i không thể truy cập được nữa.

Câu hỏi của tôi là:

Làm thế nào để đạt được một cái gì đó như thế này: while read i; do echo $i; done <(echo "$FILECONTENT") hay nói cách khác: Làm thế nào tôi có thể chắc chắn rằng i sống sót trong khi vòng lặp?

Xin lưu ý rằng tôi biết bao quanh trong khi tuyên bố thành {} nhưng điều này không giải quyết vấn đề (tưởng tượng rằng bạn muốn sử dụng vòng lặp while trong chức năng và trở i biến)

+0

http://mywiki.wooledge.org/BashFAQ/024 – tripleee

+0

Related: https://stackoverflow.com/questions/37229058/append-to-an-array-variable-from-a-pipeline-command. Giải thích tất cả các tùy chọn bao gồm thay thế quy trình được đề cập dưới đây và 'lastpipe' và ưu và khuyết điểm của chúng. –

+0

Liên quan: [Một biến được sửa đổi bên trong một vòng lặp while không được ghi nhớ] (https://stackoverflow.com/questions/16854280/a-variable-modified-inside-a-while-loop-is-not-remembered). – codeforester

Trả lời

60

Các ký hiệu chính xác cho Process Substitution là:

while read i; do echo $i; done < <(echo "$FILECONTENT") 

Giá trị cuối cùng của i được gán trong vòng lặp sẽ khả dụng khi vòng lặp kết thúc. Một giải pháp thay thế là:

echo $FILECONTENT | 
{ 
while read i; do echo $i; done 
...do other things using $i here... 
} 

Niềng răng là hoạt động nhóm I/O và không tự tạo ra vỏ bọc con. Trong ngữ cảnh này, chúng là một phần của một đường ống dẫn và do đó hoạt động như một vỏ bọc phụ, nhưng đó là vì một số |, không phải là { ... }. Bạn đề cập đến điều này trong câu hỏi. AFAIK, bạn có thể quay trở lại từ bên trong một hàm.


Bash cũng cung cấp shopt dựng sẵn và là một trong nhiều lựa chọn của nó là:

lastpipe

Nếu được đặt, và kiểm soát công việc là không hoạt động, vỏ chạy lệnh cuối cùng của một đường ống không được thực hiện trong nền trong môi trường trình bao hiện tại.

Do đó, sử dụng một cái gì đó như thế này trong một kịch bản làm cho modfied sum sẵn sau khi vòng lặp:

FILECONTENT="12 Name 
13 Number 
14 Information" 
shopt -s lastpipe # Comment this out to see the alternative behaviour 
sum=0 
echo "$FILECONTENT" | 
while read number name; do ((sum+=$number)); done 
echo $sum 

Việc làm này tại dòng lệnh thường chạy hôi của 'kiểm soát công việc không hoạt động' (có nghĩa là, tại dòng lệnh, kiểm soát công việc đang hoạt động). Kiểm tra điều này mà không sử dụng tập lệnh không thành công.

Ngoài ra, như ghi nhận của Gareth Rees trong answer của mình, bạn có thể đôi khi sử dụng một here string:

while read i; do echo $i; done <<< "$FILECONTENT" 

này không đòi hỏi shopt; bạn có thể lưu một quá trình bằng cách sử dụng nó.

+0

Tha thứ sự thiếu hiểu biết của tôi. Tôi biết đây là giải pháp đúng và tôi đã đánh dấu nó là câu trả lời để nó hoạt động cho tôi. Nhưng bây giờ khi tôi chạy 'trong khi đọc i; echo $ i; thực hiện <<(cat/etc/passwd); echo $ i' Nó không trả lại dòng cuối cùng hai lần. Tôi đang làm gì sai? –

+0

@WakanTanka: Tôi phải thử nghiệm một chút ... Tôi tin rằng câu trả lời là không đọc lại đặt lại 'i' để trống rỗng, vì vậy tiếng vang sau khi vòng lặp vang lên một dòng trống. –

+0

Kudos cho tham chiếu Thay thế quy trình. Tôi không biết. – Atcold

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