ไฟล์ Cat ต่อเทอร์มินัลที่ความเร็วของบรรทัดต่อวินาทีโดยเฉพาะ


15

ฉันขี้เกียจและฉันสามารถเขียนสคริปต์เพื่อทำสิ่งนี้ แต่ฉันก็ขี้เกียจเกินไปที่จะคิดว่าจะทำอย่างไร

ฉันมักจะทำสิ่งต่าง ๆ เช่น:

cris$ python runexperiment.py > output.txt
cris$ cat output.txt

บางครั้งเมื่อดูผลลัพธ์ที่ยาวนานของการทดสอบฉันต้องการให้หน้าเว็บเลื่อนและดูรูปแบบที่ต่อเนื่องและแยกย้ายกันไป แต่การใช้ cat บนไฟล์ที่มี 1 ล้านบรรทัดจะเสร็จสิ้นภายใน 5 วินาที นี่มันเร็วเกินไปสำหรับฉัน

มีวิธีใดบ้างที่ฉันสามารถชะลอความเร็วในการดูไฟล์ได้เช่น 'ยูทิลิตีการเลื่อน' ฉันต้องการได้อย่างรวดเร็ว แต่ไม่ถึง 200k บรรทัดต่อวินาที

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

cris$ scroll -lps=300 output.txt

จากนั้นนั่งลงและดู 300 บรรทัดต่อวินาทีที่ผ่านมาจะเหมาะอย่างยิ่ง


7
cat FILENAME | pv -l -L 900 -qลองสิ่งที่ต้องการ ขีด จำกัด อยู่ในหน่วยไบต์ต่อวินาทีไม่ใช่บรรทัดต่อวินาทีดังนั้นฉันจึงทำให้ความคิดเห็นนี้ไม่ใช่คำตอบ
David Schwartz

ตกลงดีว่าเป็นโปรแกรมที่ยอดเยี่ยมและใช้งานได้ แต่ใช่มันจะขาด ๆ หาย ๆ เล็กน้อยเนื่องจากมันไปหลังจาก bps ไม่ใช่ lps
Cris Stringfellow

คำตอบ:


17

สั้นและอ่านได้ :

perl -pe "system 'sleep .003'" log.txt

ฉันโพสต์คำตอบนี้เพราะพวกมันเล็กและอ่านง่ายเพราะความเห็นของคำตอบของ DMasดูเหมือนจะส่งเสริมการแก้ปัญหาแบบนี้!

แต่ฉันเกลียดนี้เพราะ: สำหรับระยะนี้ Perl จะแยกไป/bin/sleep300x / วินาที!

นี่คือผู้บริโภคทรัพยากรรายใหญ่! ยังเป็นทางออกที่ดีผิด!!

การใช้builtin sleep ใน

โชคไม่ดีที่ builtin sleepจำกัด จำนวนเต็ม ดังนั้นเราต้องใช้selectแทน:

perl -e 'print && select undef,undef,undef,.00333 while <>;'

ภายใต้ Perl print while <>สามารถถูกแทนที่ด้วย-pสวิตช์:

perl -pe 'select undef,undef,undef,.00333'

มาลองกัน:

time /bin/ls -l /usr/bin | perl -pe 'select undef,undef,undef,.00333' | wc
   2667   24902  171131

real    0m9.173s
user    0m0.056s
sys     0m0.048s

bc -l < <(echo 2667/9.173)
290.74457647443584432573

คำอธิบาย:

  • 300 บรรทัด / วินาทีหมายถึง 1 บรรทัดคูณ 0.0033333333 วินาที

  • printโดยไม่ต้องพิมพ์อาร์กิวเมนต์$_ซึ่งเป็นพื้นที่ป้อนข้อมูลเริ่มต้น

  • เรียกว่า... | perl -e, ... | perl -neหรือ... | perl -pe, อินพุตมาตรฐานจะถูกกำหนดโดยอัตโนมัติ*STDINซึ่งเป็นตัวบ่งชี้ไฟล์เริ่มต้นดังนั้น<>จะทำเช่นเดียวกับ<STDIN>ที่จะอ่านจากอินพุตมาตรฐานจนกระทั่ง$/( ตัวคั่นเร็กคอร์ดอินพุตซึ่งเป็นค่าเริ่มต้นขึ้นบรรทัดใหม่ ) ในภาษาอังกฤษโดยค่าเริ่มต้น<>จะอ่านหนึ่งบรรทัดจากอินพุตมาตรฐานและกำหนดเนื้อหาให้กับ$_ตัวแปร

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

  • selectเป็นเคล็ดลับของโปรแกรมเมอร์ที่จะไม่ใช้ sleepคำสั่งนี้ถูกออกแบบมาเพื่อดักจับเหตุการณ์ในfile descriptor (อินพุตและ / หรือเอาต์พุตไฟล์ซ็อกเก็ตและ / หรือซ็อกเก็ตสุทธิ) ด้วยคำสั่งนี้โปรแกรมจะรอ 3 ชนิดของกิจกรรม, อาหารพร้อมที่จะอ่าน , อาหารพร้อมที่จะเขียนและเหตุการณ์บางอย่างที่เกิดขึ้นในฟีด select <feeds where wait for input>, <feeds where having to write>, <feed where something could happen>, <timeout>อาร์กิวเมนต์ที่สี่คือหมดเวลาในวินาทีดังนั้นไวยากรณ์

เพื่อความแม่นยำมากขึ้นคุณสามารถใช้Time::Hiresโมดูล perl:

perl -MTime::HiRes -pe 'BEGIN{$start=Time::HiRes::time;$sleepPerLine=1/300};select undef,undef,undef,($start + $sleepPerLine*$. - Time::HiRes::time)'

หมายเหตุ: $.เป็นหมายเลขบรรทัดป้อนข้อมูลปัจจุบัน

เขียนได้ดีกว่าเป็น cat >catLps.pl

#!/usr/bin/perl -w

use strict;
use Time::HiRes qw|time|;

my $start=time;
my $lps=300;

$lps=shift @ARGV if @ARGV && $ARGV[0]=~/^(\d+)$/;
my $sleepPerLine=1/$lps;

print &&
    select undef,undef,undef,($start + $sleepPerLine*$. - Time::HiRes::time)
    while <>

การใช้งาน:

catLps.pl [lps] [file] [file]...

อาร์กิวเมนต์แรกlpsเป็นบรรทัดตัวเลือกต่อวินาทีอาร์กิวเมนต์ตัวเลข (ค่าเริ่มต้น: 300)

หมายเหตุ: ถ้าชื่อไฟล์เป็นตัวเลขเท่านั้นคุณอาจจะต้อง specifiy ./3พวกเขาด้วยเส้นทาง:

เช่นcatนี้สามารถส่งไฟล์ที่กำหนดเป็นอาร์กิวเมนต์และ / หรืออินพุตมาตรฐาน

ดังนั้นเราจึงสามารถ:

TIMEFORMAT='%R' 
time seq 1 100 | ./catLps.pl 100 >/dev/null 
1.040

time seq 1 10000 | ./catLps.pl 10000 >/dev/null  
1.042

เพื่อความสนุก:

export TIMEFORMAT='%R' ;clear ;time seq 1 $((LINES-2)) | ./catLps.pl $((LINES-2))

2
ดูเหมือนว่าคุณจะทำรายการวูดูอย่างจริงจัง มันเจ๋งมากฉันลองแล้วก็ใช้งานได้ ฉันไม่รู้ว่าคุณทำอย่างนั้นอย่างไร อะไรคือสิ่งที่ perl เลือก? undef? ฉันสามารถค้นหามันได้ น่าอัศจรรย์
Cris Stringfellow

2
@CrisStringfellow ตกลงฉันได้เพิ่มคำอธิบายบางอย่างและสคริปต์เต็มรูปแบบโดยใช้Time::HiResโมดูล Perl เพื่อความถูกต้องมากขึ้น
เอฟ HAURI

พระเจ้า. นั่นคือคำตอบที่ยอดเยี่ยม ขอขอบคุณ. ฉันพยายาม upvote เป็นครั้งที่สอง ฉันกำลังเรียนรู้บางอย่างโดยอ่านคำอธิบายที่ยอดเยี่ยมของคุณ
Cris Stringfellow

2
คุณสามารถ
โหวต

@CrisStringfellow คำตอบแก้ไข: โดยการใช้-pสวิตช์เป็นคำสั่ง Perl สคริปต์ก็เบาลง!
F. Hauri

11

เพียงใช้ awk ด้วย sleep:

awk '{print $0; system("sleep .1");}' log.txt

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

2
ซึ่งแตกต่างจากการแก้ปัญหา Perl มันค่อนข้างอ่านได้
Gunslinger

1
@Gunslinger: ไวยากรณ์system(*sleep .1")จะสร้าง 10 forks / วินาที! สิ่งนี้สามารถเขียนได้perl -pe 'system "sleep .1"' log.txt: อ่านได้เช่นกัน แต่มีราคาแพงมาก (ไม่ใช่ระบบที่เป็นมิตร!)
F. Hauri

ฉันก็ชอบคำตอบที่อ่านได้นี้เช่นกัน สิ่งเดียวคือมันจะยิงคำสั่ง shell sleep สำหรับทุกบรรทัดที่เอาต์พุต แต่การอ่านเขียนที่สมบูรณ์แบบฉันไม่สนใจเลย
itsafire

0

ฉันไปงานปาร์ตี้ช้า แต่ฉันพบว่านี่จะเป็นแบบฝึกหัดการเรียนรู้ที่มีประโยชน์สำหรับการทดลองใน python ดังนั้นฉันจะพูดถึงสิ่งที่ฉันได้รับ:

#!/usr/bin/env python3

import argparse
from time import sleep

parser = argparse.ArgumentParser(description='Echo a file slowly')
parser.add_argument('-i',
                    '--input-file',
                    type=argparse.FileType('r'),
                    default='-')
parser.add_argument('-d',
                    '--delay-in-ms',
                    type=int,
                    default='100')
args = parser.parse_args()

for line in args.input_file:
    print(line.rstrip())
    sleep(args.delay_in_ms/1000.0)

ยอมรับอินพุตจาก stdin หรือเป็นอาร์กิวเมนต์ (-i) และโดยค่าเริ่มต้นจะเขียนหนึ่งบรรทัดต่อ 1 / 10th ของวินาที แต่สามารถเปลี่ยนได้ด้วยอาร์กิวเมนต์อื่น (-d)


ขอบคุณ ฉันเริ่มพัฒนาบางอย่างที่คล้ายกับแนวคิดนี้ใน Python เมื่อฉันเกิดขึ้นกับคำถาม & การโฆษณานี้ ฉันทราบว่า Python ยังรองรับdocs.python.org/3/library/select.html ที่ได้รับการคัดเลือกในลักษณะเดียวกันกับ Perl ที่ใช้ในคำตอบของ F. Hauri
ybull
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.