ฉันจะส่งผ่านเอาต์พุตของคำสั่งเดียวไปยังหลายคำสั่งได้อย่างไร


20

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

ตัวอย่าง:

wc < <(echo hi;echo bye)
(echo hi; bye) | wc

แต่มีตรงกันข้ามไหม

นั่นคือมีวิธีส่งเอาต์พุตของคำสั่งเดียวเป็นอินพุตสำหรับคำสั่งอื่น ๆ ในบรรทัดเดียวหรือไม่?

สิ่งที่ต้องการ :

cat testfile | wc | tail -n 5

( อย่าใช้ท่ออย่างแท้จริง ) ที่นี่ฉันพยายามที่จะส่งออกcat testfileไปยังทั้งสองwcและtail -n 5

อีกตัวอย่างหนึ่งคือ:

( เพื่อให้ได้คำสุดท้ายของประโยค )

echo "some random words"| wc -c | cut -f(out put of wc -c) (output of first echo)

คำตอบ:


21

คำตอบที่รวดเร็ว. คุณสามารถใช้tee >(what_to_do) >(another_thing_to_do)เพื่อดำเนินการตามคำสั่งของคุณสำหรับสิ่งต่าง ๆ ที่คุณต้องการทำ

ตัวอย่าง:

ไฟล์เอาต์พุตทดสอบต้นฉบับ:

:~$ cat testfile.txt 
Device Model:     LITEONIT LCS-256M6S 2.5 7mm 256GB
Serial Number:    TW0XFJWX550854187616

เอาท์พุทด้วยteeคำสั่งเพิ่ม:

:~$ cat testfile.txt | tee >(tail -1) >(wc) >(awk '{print $3,$1,$2}')
Device Model:     LITEONIT LCS-256M6S 2.5 7mm 256GB
Serial Number:    TW0XFJWX550854187616
LITEONIT Device Model:
TW0XFJWX550854187616 Serial Number:
      2      10      91
Serial Number:    TW0XFJWX550854187616

แต่ละคำสั่งใน tee เป็นเพียงคำสั่งปกติที่คุณจะใช้กับบรรทัดคำสั่งเช่นเพิ่มใน>(head -1 | wc)งานด้วย

:~$ cat testfile.txt | tee >(tail -1) >(head -1 | wc)  >(awk '{print $3,$1,$2}')
Device Model:     LITEONIT LCS-256M6S 2.5 7mm 256GB
Serial Number:    TW0XFJWX550854187616
      1       7      52
LITEONIT Device Model:
TW0XFJWX550854187616 Serial Number:
Serial Number:    TW0XFJWX550854187616

หรือคุณสามารถคว้าคำสุดท้ายในการพูดบรรทัดสุดท้ายโดยใช้awkกับ$NFด้วยwcเช่นนี้:

:~$ cat testfile.txt | tail -1 | tee >(wc) >(awk '{print $NF}')
Serial Number:    TW0XFJWX550854187616
TW0XFJWX550854187616
      1       3      39

หมายเหตุ: การเพิ่ม|คำสั่งไพพ์ไปยังจุดสิ้นสุดสามารถลบล้างได้โดยใช้คำสั่งหลายคำสั่งจากteeคำสั่ง ฉันมีตัวอย่างที่นี่ที่ฉันได้รับการทดสอบ:

ตัวอย่างที่ 1 (คำสั่ง Pipe ดึงคำสุดท้ายทั้งหมด):

:~$ echo "This is just five words" | tee >(wc -l) >(wc -w) >(wc -c) | awk '{print $NF}'
words
24
5
1

ตัวอย่างที่ 2 (ไม่แสดงเอาต์พุตของคำสั่ง wc คำสั่ง Pipe คว้าคำที่ 3):

:~$ echo "This is just five words" | tee >(wc -l) >(wc -w) >(wc -c) | awk '{print $3}'
just

ตัวอย่างที่ 3 (จับคำที่ 3 ของ echo line คำสั่ง Tee.):

:~$ echo "This is just five words" | tee >(wc -l) >(wc -w) >(wc -c) >(awk '{print $3}')
This is just five words
just
24
5
1

ตัวอย่างที่ 4 (การรวบรวมคำสุดท้ายของบรรทัด echo คำสั่ง Tee.):

:~$ echo "This is just five words" | tee >(wc -l) >(wc -w) >(wc -c) >(awk '{print $NF}')
This is just five words
words
24
5
1

หวังว่านี่จะช่วยได้!


3
ฉันชอบชาและกาแฟ! '-)
Elder Geek

1
คำสั่งเกี่ยวกับการสั่งซื้อของเอาท์พุทระหว่างผู้บริโภคที่แตกต่างกันของteeเป็นเท็จ เหตุผลที่คุณมักจะได้รับคำสั่งที่ถูกต้องก็คือในเครื่องที่มีโหลดต่ำกระบวนการผู้บริโภคเครื่องแรกจะเริ่มทำงานก่อน บนเครื่องที่ยุ่งกว่าผู้บริโภคคนแรกอาจจะหลับก่อนที่จะพิมพ์อะไรก็ได้
Matei David

@MateiDavid ฉันไม่สามารถพิสูจน์ได้ดังนั้นฉันเพิ่งลบคำสั่ง ไม่มีปัญหา
Terrance

2
ดูคำตอบของฉัน แต่ที่จริงจังกว่านั้นคือteeไม่มีความคิดเกี่ยวกับผู้บริโภค - พวกเขาถูกสร้างขึ้นโดยbashผู้ที่ดำเนินการสาย สิ่งที่bashทำคือการคัดลอกตัวอธิบายไฟล์ที่เปิด นอกเหนือจากนั้นคุณมีผู้บริโภคจำนวนมากที่เขียนไปยังไฟล์ descriptors ที่เปิดในไฟล์เดียวกัน เคอร์เนลดูแลสิ่งนั้น แต่แน่นอนว่าลำดับที่ปรากฏบนbashบรรทัดคำสั่งจะไม่เป็นปัจจัย
Matei David

17

คุณต้องteeแบ่งสตรีมออกเป็นส่วน ๆ ลอง:

cat testfile | tee >(wc -l) >(wc -w) >(wc -c) | tail -n 5

หมายเหตุ:

  • หากกระบวนการหลายรายการ ( wc, tail) ทั้งหมดเขียนไปยัง stdout:

    • คุณอาจได้รับผลลัพธ์ที่อ่านไม่ออก

    • ไม่มีการรับประกันเกี่ยวกับการสั่งซื้อสินค้าที่จะปรากฏ หากต้องการดูสิ่งนี้ลองใช้sleep 1; wc -wในฐานะผู้บริโภครายที่สอง

  • teeจะปิดกั้นหากปลายทางใด ๆ ไม่ใช้สตรีมเร็วพอ ความหมายปลายทางจะถูกป้อนเข้าด้วยความเร็วใกล้เคียงกัน (โมดูโลการกำหนดขนาดคงที่) ไม่มีวิธีแก้ไขที่ง่ายสำหรับสิ่งนี้ทางเลือกเดียวคือบันทึกสตรีมไปยังไฟล์และป้อนให้ผู้บริโภคแยกต่างหาก สำหรับwcและtailนี่ไม่ใช่ปัญหา

สำหรับคำสุดท้ายมันง่ายกว่าที่จะทำ:

echo "some random words" | awk '{print $NF}'

5

moreutilsแพคเกจให้คำสั่งpee(ผสานของท่อและทีสิ่งที่คุณคิดว่า?) ซึ่งไม่ตรงที่

สำหรับตัวอย่างแรกของคุณคุณจะใช้:

cat testfile | pee wc "tail -n 5"

ตัวอย่างที่สองมีความซับซ้อนมากขึ้นเนื่องจากคุณต้องการส่งผ่านสองอินพุตไปยังคำสั่งสุดท้าย ฉันอาจจะใช้awkเป็นคำตอบอื่น ๆ

ลิงก์: https://joeyh.name/code/moreutils/

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