Kịch bản tiếp tục đọc một luồng


7

Đôi khi tôi catmột luồng như thế /dev/input/event0.

Tôi muốn viết một kịch bản làm một cái gì đó mỗi khi có đầu ra nhiều hơn.

Định nghĩa của đầu ra nhiều hơn có thể là mỗi khi nó đọc một byte.

Làm thế nào có thể được thực hiện? Có một số lệnh đó không?

Câu trả lời:


5

Từ một kịch bản shell, bạn sẽ bị giới hạn trong các dòng hoàn chỉnh. Bạn sẽ cần sử dụng C / Perl / Python / bất cứ thứ gì để đọc chi tiết hơn.

while read line; do
  # do something based on content of $line; remember to quote it
done </dev/input/event0

6
Nhiều shell hỗ trợ đọc ít hơn một dòng, nó chỉ là không chuẩn. ksh có thể đọc (ví dụ) năm byte với read -N5, bash có thể đọc năm ký tự (có thể là đa nhân) với read -rN5, zsh có thể đọc 5 ký tự (có thể là đa nhân) với read -u0 -k5. Cả bashzsh đều có thể đọc byte thay vì ký tự bằng cách sử dụng ngôn ngữ C (hoặc có thể là bất kỳ ký tự 8 bit nào).
Chris Johnsen

2
@Chris Hãy xem xét viết lên một câu trả lời!
Steven D

Rõ ràng read -Nlà mới trong bash 4.2, vì vậy nó có thể không ở khắp mọi nơi. Ngoài ra, bash LC_CTYPE=C IFS= read -rN 1 dường như ăn một số byte nhất định (0x00, 0xff). ksh dường như ăn 0x00 (có thể do sử dụng chuỗi kết thúc NUL trong nội bộ). zsh dường như hoạt động chính xác mặc dù.
Chris Johnsen

4

Một biến thể về câu trả lời của geekizard:
Bạn có thể muốn read -n 1 byteđọc một byte mỗi lần, sau đó làm gì đó với $byte.

BIÊN TẬP:

Chỉ cần thử điều này vì tôi chưa bao giờ sử dụng lệnh đó trước đây (chỉ nhìn lên info bash), nhưng nó dường như nhai tất cả các khoảng trắng và kết thúc dòng. Tôi chưa có lời giải thích cho điều này.

Hãy thử các tập lệnh sau để tinh chỉnh các đối số lệnh:

(for j in $(seq 1 10); do for i in $(seq 1 100); do echo -n "$i, "; sleep .02; done; echo "& $j."; done) | (while read line; do echo $line; done)

(for j in $(seq 1 10); do for i in $(seq 1 100); do echo -n "$i, "; sleep .05; done; echo "& $j."; done) | (while read -n 1 byte; do echo -n "$byte"; done)

Thật không may, điều này không mang lại kết quả như mong đợi.

EDIT (với sự giúp đỡ của Chris):

(for j in $(seq 1 10); do for i in $(seq 1 100); do echo -n "$i, "; sleep .02; done; echo "& $j."; done) | (while IFS= read -N 1 byte; do echo -n "$byte"; done)

Điều này cho kết quả chính xác.
Lưu ý: cho dù tôi sử dụng -n, -Nhoặc -rNkhông thay đổi kết quả, tất cả đều tốt (với văn bản, tôi đã không kiểm tra giới hạn mà Chris nói về: 0x00 và 0xff).


Đó là "munching" là lý do tại sao tôi nói "nhớ trích dẫn nó"; nếu bạn nói echo $foo, $foosẽ có được tất cả các khoảng trắng (tất cả các ký tự $IFS, được mô tả) được nén vào các khoảng trống đơn, trong khi echo "$foo"sẽ bảo toàn chúng. Nhưng bạn phải sử dụng nó một cách nhất quán để đảm bảo khoảng trắng luôn được trích dẫn.
geekizard

1
@geekizard, nó không phải là một vấn đề trích dẫn, đó là do thực tế là bash dường như bỏ qua các thành viên IFS trong read -n(và read -Ntrong 4.2). Cách giải quyết là sử dụng IFS= read -rn 1(ngay cả khi đó, bash vẫn ăn 0x00 và 0xff).
Chris Johnsen

Đây sẽ là lý do tại sao tôi không sử dụng bash; nó dường như luôn có những lỗi ngu ngốc như thế ( bashLỗi "yêu thích" của tôi là ở một số phiên bản 2.x trong đó dấu gạch chéo ngược trong trường hợp các mẫu không dừng lại *là một trận đấu toàn cầu.)
geekizard
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.