วิธีใช้ sed เพื่อจัดการเอาต์พุตสตรีมมิ่งอย่างต่อเนื่อง?


13

ฉันกำลังรวบรวมการนำเสนอสำหรับผู้ชมที่ไม่ใช่ด้านเทคนิค ฉันมีโปรแกรมที่ทำงานในการทุบตีที่ส่งออกกระแสอย่างต่อเนื่องของค่าบางอย่างที่มีความสำคัญ ฉันต้องการเน้นผลลัพธ์ที่สำคัญตามที่ปรากฏเพื่อให้ผู้ชมได้รับแนวคิดเกี่ยวกับความถี่ของพวกเขา ปัญหาคือฉันไม่สามารถsedทำงานบนสตรีมที่กำลังทำงานอยู่ได้ มันทำงานได้ดีถ้าฉันใส่ผลลัพธ์ลงในไฟล์เช่นเดียวกับใน:

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

แต่ถ้าฉันลองแบบเดียวกันกับเอาต์พุตที่กำลังทำงานอยู่เช่นนี้

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

sedไม่ทำอะไรเลย ความคิดใด ๆ

ขณะที่แลมเบิร์ตมีประโยชน์พอที่จะชี้ให้เห็นคำพูดของฉันที่sedไม่ทำอะไรคลุมเครือ สิ่งที่เกิดขึ้นคือการที่เอาท์พุทโปรแกรมstdout(ฉันค่อนข้างมั่นใจว่ามันไม่ได้เขียนไปstderr) sedตามที่ปกติแม้ว่ามันประปาผ่าน

ปัญหาน่าจะเป็นที่คำสั่งเรียกโปรแกรมที่สองซึ่งจากนั้นส่งออกไปยัง stdout มีบางบรรทัดที่พิมพ์โดยโปรแกรมแรก สิ่งเหล่านี้ฉันสามารถแก้ไขได้ จากนั้นจะมีกระแสของค่าที่พิมพ์โดยโปรแกรมที่สอง สิ่งเหล่านี้ฉันไม่สามารถแก้ไขได้

วิธี Perl และ awk ไม่ทำงานเช่นกัน


5
ไม่stdbuf -o0 command | sed "s/some text/some text bolded/"ทำงานหรือไม่
FloHimself

3
ด้วย 'sed ไม่มีอะไร' คุณหมายถึงว่าการทดแทนไม่ได้ทำหรือคุณไม่มีผลลัพธ์ใด ๆ ? คำสั่งอาจเขียนถึง stderr แทนที่จะเป็น stdout? หากคุณต้องการไฮไลต์สิ่งที่คุณอาจใช้command|egrep 'some text|$'
Lambert

คำสั่งเขียนไปยัง stdout (และไม่ใช่ stderr) หรือไม่?
Anthon

1
ระบุว่าข้อความปรากฏมากกว่าหนึ่งครั้งคุณควรเพิ่มการgทดแทนที่มี "ทั่วโลก" มิฉะนั้นเฉพาะที่เกิดขึ้นครั้งแรกในบรรทัดที่จะถูกแทนที่:sed "s/old/new/g"
ph0t0nix

@ ph0t0nix ไม่นั่นไม่ใช่ปัญหา แต่เป็นปัญหาที่เกิดขึ้น ขอบคุณสำหรับทิป.
P Jones

คำตอบ:


12

โอกาสที่เอาต์พุตของคำสั่งจะถูกบัฟเฟอร์ เมื่อคำสั่งเขียนไปยังเทอร์มินัลบัฟเฟอร์จะถูกฟลัชบนทุกบรรทัดใหม่ดังนั้นคุณจะเห็นว่ามันปรากฏในอัตราที่คาดหวัง เมื่อคำสั่งเขียนไปยังไพพ์บัฟเฟอร์จะถูกฟลัชเมื่อถึงไม่กี่กิโลไบต์เท่านั้นดังนั้นจึงล่าช้ามาก ดังนั้นจึงเป็นพฤติกรรมเริ่มต้นของไลบรารีอินพุต / เอาต์พุตมาตรฐาน

เพื่อบังคับให้คำสั่งไม่ส่งสัญญาณเอาต์พุตคุณสามารถใช้unbuffer(จากที่คาดไว้) หรือstdbuf(จาก coreutils ของ GNU)

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

stdbufไม่ทำงาน (มันถูกกล่าวถึงก่อนหน้านี้ BTW) แต่unbufferทำ !! คุณไม่รู้หรอกว่าคุณทำให้ฉันมีความสุขแค่ไหน
P Jones

และขอขอบคุณสำหรับคำอธิบายที่กระชับ มีประโยชน์มาก
P Jones

sedตัวเองใช้บัฟเฟอร์ดังกล่าว (cf ChennyStar โพสต์) ดังนั้นตัวอย่างที่นี่อาจใช้งานไม่ได้เนื่องจากsedเป็นcommandunbuffer: cat /etc/passwd | unbuffer sedแต่sedตัวมันเองมี-uตัวเลือกดังนั้นจึงgrepอาจมีความเหมาะสมมากกว่าในตัวอย่างนี้ ขอบคุณมากสำหรับข้อมูลพื้นหลังของคุณ! คำตอบที่ดี!
คณิตศาสตร์

4

sed มีตัวเลือกสำหรับ:

-u, - ไม่ได้จัดการ

ซึ่งโหลดข้อมูลจำนวนน้อยที่สุดจากไฟล์อินพุตและล้างบัฟเฟอร์เอาต์พุตบ่อยกว่า ดูman sedรายละเอียดเพิ่มเติมได้ที่


1
GNU sedเท่านั้น (ไม่ใช่ BSD sed) และฉันเชื่อว่าสิ่งนี้จะไม่ป้องกันการบัฟเฟอร์ของคำสั่งเมื่อเริ่มต้นไพพ์ แต่ดีที่จะพูดถึงมัน :)
สัญลักษณ์แทน

stdbuf manpage ระบุว่า "หากคำสั่งปรับบัฟเฟอร์ของสตรีมมาตรฐาน (เช่น 'tee' ทำเช่นนั้น) แล้วจะแทนที่การเปลี่ยนแปลงที่สอดคล้องกันโดย 'stdbuf'" ดูเหมือนว่า sed อาจตกอยู่ในหมวดหมู่นี้ แต่ธง '-u' จะทำให้มีประโยชน์ในห่วงโซ่ท่อที่ไม่มีบัฟเฟอร์
MattSmith

2

ฉันจะใช้ awk

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

ที่ไหน

  • /some important stuff/ เลือกบรรทัดสำคัญเช่นอยู่ใน sed
  • printf "%c[31m%s%c[0m\n",27,$0,27 ; พิมพ์ด้วยสีแดง
    • ใช้ 32,33 สำหรับสีเขียว, สีเหลือง ...
    • $ 1, $ 2, สามารถใช้เพื่อเลือกฟิลด์เฉพาะ
  • บรรทัดอื่นพิมพ์เพียง 'ตามที่เป็น'

จุดสำคัญคือcommandควรล้างข้อมูลบรรทัด แต่ควรเป็นกรณีนี้หากคุณมีเอาต์พุตจำนวนมาก


หมายเหตุ: คำถามไม่ได้บอกว่าทั้งบรรทัดควรเป็น "ตัวหนา" แต่เพียง "บางข้อความ" ในขณะที่เป็นไปได้ที่จะใช้คุณลักษณะนั้นในawk(ใช้sub()หรือgsub()) ในกรณีของการทดแทนแบบดั้งเดิมนี้sedเป็นเครื่องมือที่เหมาะสมอย่างแน่นอน
Janis

1

วิธี perl:

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

หรือเอาท์พุทอย่างต่อเนื่อง:

สคริปต์ทุบตีสำหรับผลลัพธ์cont:

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

ทดสอบกับ:

./cont | perl -pe 's/(stuff)/\x1b[1m${1}\x1b[0m/g'
  • \x1b[1m - ตัวหนาหรือเพิ่มความเข้ม
  • ${1} - backreferenze
  • \x1b[0m - รีเซ็ตคุณสมบัติทั้งหมด

เอาท์พุท:

บางสิ่ง
บางสิ่ง
บางสิ่ง
บางสิ่ง

รหัสหนีเพิ่มเติมที่นี่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.