Làm thế nào để sử dụng sed để thao tác đầu ra liên tục?


13

Tôi đang tập hợp một bài thuyết trình cho một đối tượng phi kỹ thuật. Tôi có một chương trình đang chạy trong bash tạo ra một luồng giá trị liên tục, một vài trong số đó là quan trọng. Tôi muốn làm nổi bật các kết quả quan trọng khi chúng được hiển thị để khán giả có thể biết được tần suất của chúng. Vấn đề là tôi không thể sedhoạt động trên một luồng đang chạy. Nó hoạt động tốt nếu tôi đặt kết quả vào một tệp, như trong:

cat output.txt | sed "s/some text/some text bolded/"

Nhưng nếu tôi thử điều tương tự trên đầu ra đang chạy, như thế này:

command | sed "s/some text/some text bolded/"

sedKhông lam gi cả. Có suy nghĩ gì không?

Như Lambert đủ hữu ích để chỉ ra, câu nói của tôi sedkhông có gì là mơ hồ. Điều đang xảy ra là chương trình xuất ra stdout(tôi khá chắc chắn rằng nó không được ghi vào stderr) như bình thường, ngay cả khi nó được chuyển qua sed.

Vấn đề dường như là lệnh gọi một chương trình thứ hai, sau đó xuất ra thiết bị xuất chuẩn. Có một vài dòng được in bởi chương trình đầu tiên; những cái này tôi có thể chỉnh sửa. Sau đó, có một luồng các giá trị được in bởi chương trình thứ hai; những cái này tôi không thể chỉnh sửa.

Phương pháp Perl và awk cũng không hoạt động.


5
stdbuf -o0 command | sed "s/some text/some text bolded/"hoạt động không?
FloHim mình

3
Với 'sed không có gì', bạn có nghĩa là sự thay thế không được thực hiện, hoặc bạn không có bất kỳ đầu ra nào? Lệnh có thể được viết vào stderr thay vì stdout? Nếu bạn muốn làm nổi bật thứ gì đó bạn có thể sử dụngcommand|egrep 'some text|$'
Lambert

Là lệnh viết để stdout (và không để stderr)?
Anthon

1
Cho rằng văn bản xuất hiện nhiều hơn một lần, bạn nên thêm gthay thế "toàn cầu", nếu không, chỉ lần xuất hiện đầu tiên trên một dòng sẽ được thay thế:sed "s/old/new/g"
ph0t0nix

@ ph0t0nix Không, đó không phải là vấn đề, nhưng nó sẽ là một vấn đề. Cảm ơn vì tiền hỗ trợ.
P Jones

Câu trả lời:


12

Rất có thể là đầu ra của lệnh được đệm. Khi lệnh ghi vào một thiết bị đầu cuối, bộ đệm được xóa trên mỗi dòng mới, vì vậy bạn thấy nó xuất hiện ở tốc độ dự kiến. Khi lệnh ghi vào một đường ống, bộ đệm chỉ bị xóa khi đạt đến một vài kilobyte, vì vậy nó bị trễ rất nhiều. Do đó, là hành vi mặc định của thư viện đầu vào / đầu ra tiêu chuẩn.

Để buộc lệnh không tự chọn đầu ra của nó, bạn có thể sử dụng unbuffer(từ mong đợi) hoặc stdbuf(từ lõi core GNU).

unbuffer command | sed …
stdbuf -o0 command | sed …

stdbufđã không hoạt động (nó đã được đề cập trước đó, BTW), nhưng unbufferđã làm !! Bạn không biết bạn đã làm tôi hạnh phúc như thế nào.
P Jones

Và cảm ơn bạn đã giải thích ngắn gọn. Rất hữu ích.
P Jones

sedchính nó sử dụng một bộ đệm như vậy, (cf ChennyStar post) vì vậy các ví dụ ở đây có thể không hoạt động vì đó sedcommandunbuffer: cat /etc/passwd | unbuffer sednhưng sedbản thân nó có một -utùy chọn, vì vậy grepcó thể phù hợp hơn trong ví dụ này. Cảm ơn rất nhiều cho thông tin lý lịch của bạn! Câu trả lời chính xác!
toán

4

sed có một tùy chọn cho điều đó:

-u, - bị xáo trộn

Việc tải lượng dữ liệu tối thiểu từ các tệp đầu vào và xóa bộ đệm đầu ra thường xuyên hơn. Xem man sedđể biết thêm chi tiết.


1
GNU sedchỉ (không phải BSD sed) và tôi tin rằng điều này vẫn không ngăn được việc đệm lệnh khi bắt đầu đường ống. Nhưng tốt để đề cập đến nó. :)
tự đại diện

trang mandb stdbuf nói rằng "Nếu LỰA điều chỉnh bộ đệm của các luồng tiêu chuẩn của nó (ví dụ 'tee') thì điều đó sẽ ghi đè các thay đổi tương ứng bằng 'stdbuf'." Có vẻ như sed có thể rơi vào loại này nhưng cờ '-u' sẽ làm cho nó hữu ích trong chuỗi ống không có bộ đệm.
MattSmith

2

Tôi sẽ sử dụng awk

  command | awk '/some important stuff/ { printf "%c[31m%s%c[0m\n",27,$0,27 ; next }
  { print ; } '

Ở đâu

  • /some important stuff/ chọn dòng quan trọng, như trong sed
  • printf "%c[31m%s%c[0m\n",27,$0,27 ; in màu đỏ
    • sử dụng 32,33 cho màu xanh lá cây, màu vàng ...
    • $ 1, $ 2, có thể được sử dụng để chọn một trường cụ thể
  • dòng khác chỉ được in 'như là'

điểm quan trọng là commandphải tuôn ra các dòng, nhưng đó là trường hợp nếu bạn có nhiều đầu ra.


Lưu ý: Câu hỏi không nói rằng toàn bộ dòng nên được "in đậm", mà chỉ là "một số văn bản". Mặc dù có thể thực hiện tính năng đó trong awk(sử dụng sub()hoặc gsub()), trong trường hợp thay thế nguyên thủy sednày chắc chắn là công cụ thích hợp.
Janis

1

Cách perl:

command | perl -pe 's/(stuff)/\x1b[1m$1\x1b[0m/g'

hoặc với một đầu ra liên tục:

Một tập lệnh bash cho đầu ra cont:

#!/bin/bash
while [ true ]
do
   echo "Some stuff"
done

Kiểm tra với:

./cont | perl -pe 's/(stuff)/\x1b[1m${1}\x1b[0m/g'
  • \x1b[1m - cường độ đậm hoặc tăng
  • ${1} - phản ứng ngược
  • \x1b[0m - thiết lập lại tất cả các thuộc tính

Đầu ra:

Một số thứ
Một số thứ
Một số thứ
Một số thứ

Thêm mã thoát ở đây .

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.