Đường ống với Moreutils ts


9

Tôi có một luồng đến tại một cổng nối tiếp, với các dòng mới xuất hiện khoảng một lần mỗi giây

wren@Raven:~$ cat /dev/ttyUSB0

A_Sensor1,B_22.00,C_50.00

A_Sensor1,B_22.00,C_50.00

A_Sensor1,B_22.00,C_50.00

A_Sensor1,B_22.00,C_50.00

A_Sensor1,B_22.00,C_50.00

Tôi muốn xóa các dòng trống và dấu thời gian còn lại.

sed sẽ loại bỏ các dòng trống và thêm dấu thời gian, nhưng tôi không thể thực hiện cập nhật dấu thời gian, nó chỉ báo cáo thời gian nó được gọi:

wren@Raven:~$ cat /dev/ttyUSB0 | sed -e '/^$/d' -e "s/$/`date +\,%F\,%T`/"
A_Sensor1,B_22.00,C_50.00,2014-05-14,09:44:42
A_Sensor1,B_22.00,C_50.00,2014-05-14,09:44:42
A_Sensor1,B_22.00,C_50.00,2014-05-14,09:44:42
A_Sensor1,B_22.00,C_50.00,2014-05-14,09:44:42
A_Sensor1,B_22.00,C_50.00,2014-05-14,09:44:42
A_Sensor1,B_22.00,C_50.00,2014-05-14,09:44:42
A_Sensor1,B_22.00,C_50.00,2014-05-14,09:44:42
^C

Tôi đã tìm thấy ts, một phần của Moreutils và có thể truy cập vào đó để có dấu thời gian cập nhật.

wren@Raven:~$ cat /dev/ttyUSB0 |  ts
May 14 09:49:26 A_Sensor1,B_22.00,C_50.00
May 14 09:49:26
May 14 09:49:27 A_Sensor1,B_22.00,C_50.00
^C

Tuy nhiên, tôi không thể kết hợp đúng cách với ts.

Điều này, có vẻ như nó sẽ làm những gì tôi muốn, không tạo ra đầu ra nào cả

wren@Raven:~$ cat /dev/ttyUSB0 | sed -e '/^$/d' | ts
^C
wren@Raven:~$

Tuy nhiên, việc đảo ngược thứ tự của các đường ống sẽ tạo ra một đầu ra, nhưng tất nhiên không phải là các đường dải không còn trống. Các sự thay thế khác hoạt động tốt, vì vậy tôi biết đường ống để sed đang hoạt động.

wren@Raven:~$ cat /dev/ttyUSB0 |  ts | sed -e '/^$/d'
May 14 10:07:25 A_Sensor1,B_22.00,C_50.00
May 14 10:07:25
May 14 10:07:26 A_Sensor1,B_22.00,C_50.00
May 14 10:07:26
^C

Vì vậy, tôi có một chút trở ngại. Tôi có thể làm cho sed loại bỏ các dòng không mong muốn, nhưng việc đánh dấu lại chúng trước khi loại bỏ phải là cách tiếp cận sai.

Tôi sẽ đánh giá cao một lời giải thích và một số trợ giúp.

Câu trả lời:


9

Để trả lời câu hỏi trực tiếp, sedbộ đệm và đó là vấn đề duy nhất.
Bạn có thể sửa lỗi này bằng cách yêu cầu nó không đệm với -u/ --unbufferedcờ của nó :

sed -u '/^$/d' /dev/ttyUSB0 | ts

Với khai thác thử nghiệm (nhưng bạn sẽ cần chạy nó để chứng minh):

$ (echo -e 'banana\n\n'; sleep 2; echo 'cheese') | sed -u '/^$/d' | ts
May 14 11:26:05 banana
May 14 11:26:07 cheese

Bạn có thể gặp phải những khó khăn tương tự với các trình soạn thảo luồng khác. Dường như tất cả đều muốn đệm một chút. Họ đều có cách giải quyết mặc dù. Dưới đây là một loạt các lệnh tôi đã thử nghiệm:

... | mawk -W interactive '/./' | ts
... | gawk '/./ { print $0; fflush(); }' | ts
... | grep --line-buffered '.' | ts
... | perl -n -e 'print if /./' | ts

Một ý tưởng khác là chỉ để cho gawknó xử lý nó. Nó có thể lọc các dòng không trống và thực hiện in ngày cho bạn (nhờ vào Kieron của SO ):

awk '/./ { print strftime("%Y-%m-%d %H:%M:%S"), $0; fflush(); }' /dev/ttyUSB0

Điều đó tuôn ra ngay sau khi các dòng vào. gawkĐặc biệt hữu ích ở đây nếu bạn muốn làm những việc khác ... Nếu bạn muốn kiểm tra xem cột đầu ra thứ tư (trước ts) có khớp với biểu thức chính quy không, bạn có thể (ví dụ $4~/\d{4}/). Awk (và các biến thể của nó) rất linh hoạt để xử lý luồng.

Một khai thác thử nghiệm khác:

$ gawk '/./ { print strftime("%Y-%m-%d %H:%M:%S"), $0; fflush(); }' <(
      echo -e 'banana\n\n';
      sleep 2;
      echo 'cheese'
  )
2014-05-14 11:13:59 banana
2014-05-14 11:14:01 cheese

1
+1 cho sed -u. Đây là một vấn đề về bộ đệm so với bộ đệm dòng.
jfs

@Oli sed -u cũng hoạt động hoàn hảo khi được dẫn vào ts, vì vậy tôi sẽ đọc về bộ đệm. Tôi không còn gặp khó khăn nữa, cảm ơn rất nhiều.
bối rối

awk đặc biệt phù hợp với những thứ như thế này mã awk thường dày đặc hơn và dễ đọc hơn nhiều so với sed và bạn có thể gửi bao nhiêu câu lệnh in mà bạn muốn xem kết quả một phần trong khi gỡ lỗi. Bạn có thể đặt toàn bộ chương trình awk vào tài liệu ở đây để tránh sử dụng một tệp riêng và nếu bạn đặt dấu ngoặc kép quanh chuỗi kết thúc tài liệu ở đây, thì bash sẽ bỏ qua tất cả các mã thông báo được nhúng mà nó thường cố gắng diễn giải.
Joe

0

bash có thể xử lý việc này trong một while readvòng lặp

(echo -e 'banana\n\n'; sleep 2; echo 'cheese') | 
while IFS= read -r line; do 
    [[ $line ]] && echo "$(date "+%F %T") line"
done
2014-05-14 06:34:06 banana
2014-05-14 06:34:08 cheese

Bạn có thể xóa các dòng chỉ có khoảng trắng bằng cách mở rộng tham số khó khăn: xóa tất cả các khoảng trắng hàng đầu và xem dòng đó có trống không:

shopt -s extglob

(echo -e '  banana\n\t\n'; sleep 2; echo 'cheese') |
while IFS= read -r line; do
    [[ "${line/#+([[:blank:]])/}" ]] && echo "$(date "+%F %T") $line"
done

Tôi đã thử một loạt các cách tiếp cận như vậy, không ai trong số họ làm việc. Tôi cũng không thể lấy mã của bạn để làm việc. Sử dụng echo hoặc cat để gửi / dev / ttyUSB0 vào vòng lặp while chỉ dẫn đến một dòng đầu ra duy nhất: 2014-05-14 12:23:32
bối rối vào

Tôi chắc chắn có một cách tốt hơn, nhưng hãy thử tail -f /dev/ttyUSB0thay vì mèo hoặc tiếng vang. Nó sẽ tiếp tục chạy. Tôi không biết làm thế nào để kiểm tra điều này trên hệ thống của tôi.
Joe

tail -f / dev / ttyUSB0 không cho đầu ra, có hoặc không có vòng lặp while. tvm cho ý kiến ​​của bạn.
bối rối
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.