นับจำนวนบรรทัดของเอาต์พุตจากโปรแกรมก่อนหน้า


32

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

ฉันสามารถทำได้program | wc -lแต่นั่นจะไม่แสดงผลลัพธ์ให้กับผู้ใช้ เท่าที่ฉันรู้ฉันต้องทำprogram; program | wc -l- แต่โปรแกรมใช้เวลาอย่างน้อยหนึ่งนาทีในการทำงานดังนั้นฉันไม่ต้องการทำมากกว่าหนึ่งครั้งเพื่อแสดงการนับบรรทัดที่ด้านล่าง

แก้ไข:

  • มีวิธีการแสดงผลตามที่เกิดขึ้น (ทีละบรรทัด) แล้วส่งกลับนับในตอนท้าย?

วิธีการ: ให้โปรแกรมติดตามเอาท์พุทของตัวเองและอ่านค่าจากตัวแปร (เช่นSTDOUT_WRITE_COUNT) หรือบันทึกลงในไฟล์ / API ที่ส่วนท้ายของโปรแกรม WDYT?
mecampbellsoup

คำตอบ:


43

คุณสามารถใช้teeเพื่อแยกสตรีมเอาต์พุตที่ส่งหนึ่งสำเนาไปยังwcและอีกสำเนาหนึ่งไปยัง STDOUT เหมือนปกติ

program | tee >(wc -l)

>(cmd)ไวยากรณ์ทุบตีซึ่งหมายถึงการทำงานcmdและแทนที่>(cmd)บิตที่มีเส้นทางไปยัง (ไปป์ที่มีชื่อเชื่อมต่อกับ) ที่โปรแกรม STDIN


2
>(cmd)เป็นkshไวยากรณ์ยังได้รับการยอมรับโดยzshและbashและเป็นเพียงการใช้ท่อชื่อ/dev/fd/nในระบบที่ไม่ได้มี
Stéphane Chazelas

@StephaneChazelas ใช่หอยส่วนใหญ่สนับสนุน แต่มันไม่ได้อยู่ใน POSIX ดังนั้นมันจึงไม่สามารถพึ่งพาได้ทุกที่
แพทริค

ใช่ฉันแค่ชี้ให้เห็นว่าการทดแทนกระบวนการไม่ใช่bashสิ่งประดิษฐ์เนื่องจากถ้อยคำในคำตอบของคุณอาจทำให้ใครเชื่อ
Stéphane Chazelas

1
@TheLibbster ขึ้นอยู่กับวิธีที่คุณกำหนดประสิทธิภาพ วิธีนี้เกี่ยวข้องกับการวางไข่ 2 กระบวนการเพิ่มเติมโดยที่sedและawkเป็นเพียงกระบวนการเดียว แต่teeและwcทั้งคู่ก็เล็กมาก (เล็กกว่าsedและawkมาก)
แพทริค

1
@TheLibbster ใช่ตามการทดสอบง่ายๆที่ฉันเพิ่งทำมันเร็วจริง ๆ เกี่ยวกับทั้งสองอย่างsedและawkวิธีการ (ผมddd 100MB ของ/dev/urandomไปยังแฟ้มแล้ววิ่งแฟ้มที่ผ่านแต่ละวิธีการหลายครั้ง)
แพทริค

10

ทางเลือกหนึ่งคือใช้ awk ซึ่งสามารถทำการนับและพิมพ์ไปยัง stdout

program | awk '{ print } END { print NR }'

ในawkNR คือหมายเลขบรรทัดปัจจุบัน คุณสามารถทำเช่นเดียวกันกับ perl:

program | perl -pe 'END {print "$.\n"}'

หรือsed:

program | sed -n 'p;$='

มีวิธีในการแสดงผลลัพธ์ที่เกิดขึ้น (ทีละบรรทัด) แล้วส่งกลับจำนวนที่สิ้นสุดหรือไม่
Libbux

6

คุณสามารถโคลน stdout บน stderr

program | tee /dev/stderr | wc -l

ด้วยวิธีนี้programstdout ของจะถูกส่งไปteeยัง stderr ซึ่งพิมพ์อยู่บนคอนโซล teeยังเขียนข้อมูลประปาไปเพื่อ stdout wcซึ่งเป็นประปาเพื่อ


3

ตัวเลือกที่ฉันชอบ:

program | grep "" -c

1
OP อาจจะถามอย่างอื่น แต่ฉันมาที่นี่เพื่อหาจำนวนบรรทัดที่เอาท์พุทและไม่สนใจที่จะแสดงผลลัพธ์ที่แท้จริงและมันก็ทำงานได้ ขอบคุณ!
Nikhil VJ

0
tail -f /var/log/squid/access.log | ( c=0; pl() { echo $c; c=0; }; trap pl SIGHUP; while read a; do (( c=c+1 )); done ) & ( trap 'kill $! ; exit' SIGINT; trap '' SIGHUP; while true; do kill -HUP $! ; sleep 1; done)

0

นี่อาจจะมาสาย แต่ฉันจะตอบคำถามติดตามของคุณเกี่ยวกับวิธีจับหมายเลขที่นับในตัวแปร

YOUR_VAR=$(PROGRAM | tee /dev/stderr | wc -l)นี่คือสิ่งที่คุณต้องการ

เราใช้ประโยชน์จากการteeสร้างสตรีมสองรายการที่นี่และนำไปหนึ่งรายการ/dev/stderrซึ่งจะปรากฏบนหน้าจอของคุณและอีกรายการหนึ่งไปยังwc -lซึ่งจะรายงานจำนวนบรรทัด

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