Sử dụng dịch vụ trong khi đọc bản tin trên nền tảng linux


34

Ai đó có thể vui lòng giải thích làm thế nào mã sau đây hoạt động?

echo '1 2 3 4 5 6' | while read a b c
do
  echo $c $b $a
done

Cụ thể, tôi muốn biết tại sao đầu ra của vòng lặp này 3 4 5 6 2 1, thay vì 3 2 16 5 4trên hai dòng riêng biệt? Tôi dường như không thể bao bọc tâm trí của mình xung quanh nó ...

Câu trả lời:


41

readđọc toàn bộ một dòng từ đầu vào tiêu chuẩn, chia dòng thành các trường và gán các trường này cho các biến đã cho. Nếu có nhiều phần hơn biến, các phần còn lại được gán cho biến cuối cùng.

Trong trường hợp của bạn $ađược chỉ định 1, $bđược chỉ định 2$ccòn lại 3 4 5 6.


Cảm ơn anh bạn! Bây giờ nó có ý nghĩa ... Vì một số lý do, tôi nghĩ rằng không gian sẽ phân định từng cách đọc, nhưng dường như là không. Tôi đánh giá cao sự giúp đỡ của bạn!!
linuxgringo

24

Viết lại vòng lặp theo cách này cho thấy những gì đang xảy ra:

echo '1 2 3 4 5 6' | while read a b c
  do
    echo '(iteration beginning)' a="$a" b="$b" c="$c" '(iteration ending)'
  done

Điều này mang lại, như đầu ra của nó:

(iteration beginning) a=1 b=2 c=3 4 5 6 (iteration ending)

Đầu tiên lưu ý rằng chỉ có một lệnh echo duy nhất được chạy. Nếu nó được chạy nhiều hơn một lần, trong số những thứ khác, bạn sẽ thấy (iteration beginning)và các (iteration ending)chuỗi con được in nhiều lần.

Điều này để nói rằng có một whilevòng lặp ở đây không thực sự hoàn thành bất cứ điều gì. Nội readdung này đọc văn bản được phân tách bằng khoảng trắng 1 vào mỗi biến được chỉ định. Đầu vào bổ sung được nối vào cuối biến cuối được chỉ định. 2 Do đó, biến abnhận các giá trị 12tương ứng, trong khi cđảm nhận giá trị 3 4 5 6.

Khi điều kiện vòng lặp ( while read a b c) được đánh giá lần thứ hai, không có thêm đầu vào nào từ đường ống (chúng tôi chỉ đưa nó vào một dòng văn bản), do đó readlệnh đánh giá thành sai thay vì đúng và vòng lặp dừng (trước khi thực hiện cơ thể lần thứ hai).

1 : Để trở thành kỹ thuật và đặc biệt, các readBUILTIN , khi thông qua tên biến như các đối số, đọc đầu vào, tách nó thành "chữ" riêng biệt khi nó chạm trán IFS khoảng trắng (xem thêm câu hỏi nàybài viết này ).

2 : read's hành vi gây nhiễu bất kỳ trường bổ sung yếu tố đầu vào biến cuối cùng quy định không trực giấc với nhiều scripters, lúc đầu. Sẽ dễ hiểu hơn khi bạn xem xét điều đó, như câu trả lời của Florian Diesch nói , readsẽ luôn luôn (cố gắng) đọc cả một dòng - và điều đó readđược dự định là có thể sử dụng được cả có và không có vòng lặp.


Eliah, cảm ơn vì đã dành thời gian để giải thích tất cả các chi tiết. Tôi nghi ngờ rằng whilenó không phục vụ mục đích bình thường của nó trong ví dụ này, nhưng sau đó readlệnh đã ném tôi đi ... Bằng cách nào đó, tôi đã giải thích nó là "trong khi read a b ckhông sai, làm echo ...". Cảm ơn bạn đã giải thích làm thế nào nó thực sự làm việc. Tôi đã xem qua mã này ngày hôm qua và biết rằng nó sẽ lỗi tôi cho đến khi tôi phát hiện ra nó ... lol
linuxgringo

@linuxgringo Trên thực tế, thân vòng lặp được thực thi mỗi lần read a b cđánh giá là đúng và điều kiện vòng lặp ( read a b c) không chạy nhiều lần. Bit nó chỉ đánh giá đúng lần đầu tiên. Lần thứ 2, không có thêm đầu vào nào được đọc từ đường ống, do đó, cuối tập tin gặp phải, gây ra readtrả về sai . (Xem phần cuối cùng của sản lượng help read, về "Tình trạng Exit" để biết chi tiết, lưu ý rằng, trong kịch bản vỏ, không có nghĩa là sự thật và các phương tiện khác không sai.) Nếu bạn cấp nước tập trung nhiều hơn một dòng đầu vào while read ..., cơ thể lặp sẽ được thực hiện nhiều lần.
Eliah Kagan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.