2011-10-04 31 views
9

Tôi cần đọc một số dữ liệu cấu hình vào các biến môi trường trong tập lệnh bash.bash coproc và sản lượng coproc còn sót lại

Các mô hình "rõ ràng" (nhưng không chính xác) là:

egrep "pattern" config-file.cfg | read VAR1 VAR2 VAR3 etc... 

này thất bại vì read được chạy trong một subshell và do đó không thể thiết lập các biến trong vỏ cách gọi. Vì vậy, tôi đã đưa ra điều này như một cách thay thế

coproc egrep "pattern" config-file.cfg 
read -u ${COPROC[0]} VAR1 VAR2 VAR3 etc... 

hoạt động tốt.

Để kiểm tra những gì sẽ xảy ra nếu coprocess trả về nhiều hơn một dòng, tôi đã cố gắng này:

coproc cat config-file.cfg 
read -u ${COPROC[0]} VAR1 VAR2 VAR3 etc... 

nơi config-file.cfg chứa ba dòng.

$ cat config-file.cfg 
LINE1 A1 B1 C1 
LINE2 A2 B2 C2 
LINE3 A3 B3 C3 

Tôi dự kiến ​​điều này sẽ xử lý dòng đầu tiên trong tệp, theo sau là một số thông báo lỗi "đường ống bị hỏng". Trong khi nó đã làm xử lý dòng đầu tiên, không có thông báo lỗi và không có coprocess nào được chạy.

Vì vậy, tôi sau đó thử như sau trong một kịch bản:

$ cat test.sh 
coproc cat config-file.cfg 
read -u ${COPROC[0]} VAR1 VAR2 VAR3 VAR4 
echo $VAR1 $VAR2 $VAR3 $VAR4 
wait 
echo $? 

Chạy nó:

$ bash -x test.sh 
+ read -u 63 VAR1 VAR2 VAR3 VAR4 
+ cat config-file.cfg 
LINE1 A1 B1 C1 
+ wait 
+ echo 0 
0 

đâu hai dòng còn lại đi đâu? Tôi đã có thể mong đợi hoặc là "đường ống bị hỏng", hoặc wait để treo vì không có gì để đọc các dòng còn lại, nhưng như bạn có thể thấy mã trả về là số không.

+3

Trừ khi tôi bỏ sót điều gì đó, một cái gì đó như 'đọc VAR1 VAR2 VAR3 <<(egrep" pattern "config-file.cfg)' sẽ đủ, phải không? –

+0

@ShawnChin: đó là bỏ qua câu hỏi. Coprocs là những lý do chính đáng để giải thích rằng OP không phải giải thích trước tiên – sehe

+1

Xin lỗi vì sự thiếu hiểu biết của tôi. Tôi thừa nhận coprocs là mát mẻ, nhưng bình luận là một phản ứng với một suy nghĩ đi qua rằng coprocs có thể là một overkill nếu nó chỉ đơn giản là để tránh 'đọc chạy trong một subshell và mất các vars. Tôi có thể nhầm lẫn, như thường lệ. –

Trả lời

5

Theo nhận xét ở trên, bạn có thể sử dụng process substitution để đạt được điều đó. Bằng cách này, read không được chạy trong một vỏ và các vars bị bắt sẽ có sẵn trong trình bao hiện tại.

read VAR1 VAR2 VAR3 < <(egrep "pattern" config-file.cfg) 

"Nếu < (danh sách) hình thức được sử dụng, các tập tin thông qua như là một cuộc tranh cãi cần được đọc để có được đầu ra của danh sách" - cái gì "tập tin thông qua như là một agrument" là họ nói về?

Điều đó khá khó hiểu đối với tôi.chapter on process substitution trong Hướng dẫn tạo kịch bản lệnh nâng cao có giải thích toàn diện hơn.

Cách tôi thấy, khi cú pháp <(cmd) được sử dụng, ouput của cmd được tạo sẵn thông qua một đường ống có tên (hoặc tệp tạm thời) và cú pháp được thay thế bằng tên tệp của đường ống/tệp. Vì vậy, ví dụ ở trên, nó sẽ kết thúc được tương đương với:

read VAR1 VAR2 VAR3 < /dev/fd/63 

nơi /dev/fd/63 là ống tên kết nối với thiết bị xuất chuẩn của cmd.

+0

Hoàn hảo, cảm ơn! Tôi theo liên kết bạn cung cấp, và bây giờ trong bộ sưu tập tham chiếu bash vĩnh viễn của tôi :-) –

+0

Vui vì tôi có thể giúp :) –

2

Nếu tôi hiểu đúng câu hỏi của bạn (và tôi hy vọng tôi không nêu rõ ràng), đọc đọc một dòng tại một thời điểm, như trong:

$ read a b c < config-file.cfg && echo $? 
0 

hay:

$ printf '%s\n%s\n' one two | { read; echo "$REPLY";} 
one 

$ echo ${PIPESTATUS[@]} 
0 0 

Để đọc tất cả các đầu vào bạn sẽ cần một vòng lặp:

$ coproc cat config-file.cfg 
[1] 3460 

$ while read -u ${COPROC[0]} VAR1 VAR2 VAR3; do echo $VAR1 $VAR2 $VAR3; done 
LINE1 A1 B1 C1 
LINE2 A2 B2 C2 
LINE3 A3 B3 C3 
[1]+ Done     coproc COPROC cat config-file.cfg 

Chỉ cần thêm rằng điều này được giải thích trong FAQ.

+1

Không, tôi hiểu rằng 'đọc' đọc một dòng tại một thời điểm. Những gì tôi đã tự hỏi là những gì đã xảy ra với các dòng đệm khi bạn chỉ đọc một trong số họ. Tôi đã mong đợi một lỗi hoặc treo, nhưng họ chỉ biến mất, mà thực sự là những gì tôi muốn, nhưng tôi ghét "ma thuật" tôi không hiểu và không thể dự đoán. –

+0

Các đồng proc chỉ không chờ đợi cho bạn để đọc đầu vào của nó (giống như một đường ống thông thường), nó lần ra. Hãy xem xét những điều sau đây: '$ {echo 1; echo 2;} 2' và '$ {echo 1; echo 2;} | { đọc; echo $ REPLY; } 1'. Trường hợp 2 đã đi đâu? –

+0

Vì vậy, để cải cách câu trả lời: trong trường hợp này, quá trình đồng thoát ra khi nó thấy một tập tin cuối cùng trên đầu vào của nó. Bart Shaefer đã viết một hướng dẫn rất hay về các quy trình đồng, bạn có thể tìm thấy nó ở đây (http://www.zsh.org/mla/users/2011/msg00095.html). –

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