File Cat ke terminal dengan kecepatan garis per detik tertentu

11

Saya malas dan saya bisa menulis naskah untuk melakukan ini, tetapi saya bahkan terlalu malas untuk memikirkan bagaimana melakukannya.

Saya sering melakukan hal-hal seperti:

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

Kadang-kadang ketika melihat hasil panjang dari percobaan, saya ingin membiarkan halaman itu hanya bergulir dan menonton pola-pola yang berurutan terbentuk dan tersebar. Tetapi menggunakan cat pada file dengan 1 juta baris selesai dalam mungkin 5 detik. Ini terlalu cepat bahkan untukku.

Apakah ada cara saya bisa memperlambat kecepatan melihat file, seperti 'utilitas gulir'? Saya ingin cepat, tetapi tidak 200k baris per detik (yang semuanya mungkin tampilan bahkan tidak akan pernah mendaftar).

Sesuatu seperti

cris$ scroll -lps=300 output.txt

Dan kemudian duduk dan menonton 300 baris per detik melewati akan ideal, saya kira.

Cris Stringfellow
sumber
6
Coba sesuatu seperti cat FILENAME | pv -l -L 900 -q. Batasnya adalah dalam byte per detik, bukan garis per detik, jadi saya membuat ini sebagai komentar, bukan jawaban.
David Schwartz
Baiklah, itu adalah utilitas yang keren, dan itu berfungsi sebagian. Tapi ya, ini sedikit berombak karena berjalan setelah bps bukan lps.
Cris Stringfellow

Jawaban:

12

Ada beberapa utilitas yang memungkinkan Anda menentukan tarif, seperti pv, tapi kecepatannya dalam byte per detik, bukan garis per detik.

Tetapi jika Anda benar-benar ingin menggunakan lps, Anda bisa melakukan ini:

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

Di bawah perl, print while <> dapat diganti oleh -p beralih:

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

Mari mencoba:

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

Penjelasan:

  • 300 baris / detik berarti 1 baris dengan 0,0033333333 detik.

  • print tanpa cetakan argumen $_ yang mana ruang input default .

  • disebut sebagai ... | perl -e, ... | perl -ne atau ... | perl -pe, input standar akan secara otomatis ditetapkan *STDIN yang mana deskriptor file default jadi <> akan melakukan hal yang sama seperti <STDIN> yang akan membaca dari input standar hingga $/ ( input pemisah rekaman yang secara default a garis baru ) akan tercapai. Dalam bahasa Inggris, secara default <> akan membaca satu baris dari input standar dan menetapkan konten ke $_ variabel.

  • && adalah dan kondisi, tetapi digunakan di sana sebagai pemisah perintah rantai jadi setelah (berhasil) mencetak satu baris, lakukan perintah berikutnya.

  • select adalah Trik programmer untuk tidak menggunakan sleep. Perintah ini dirancang untuk menjebak peristiwa deskriptor file (input dan / atau output, file, soket dan / atau soket net). Dengan perintah ini, sebuah program bisa Tunggu untuk 3 jenis acara, feed siap dibaca , feed siap untuk ditulis dan beberapa peristiwa terjadi saat makan . Argumen keempat adalah batas waktu dalam detik, jadi sintaksnya adalah select <feeds where wait for input>, <feeds where having to write>, <feed where something could happen>, <timeout>.

Untuk lebih presisi, Anda bisa menggunakannya Time::Hires modul perl:

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

catatan: $. aku s nomor jalur input saat ini .

Lebih baik ditulis sebagai 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 <>

Pemakaian:

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

Argumen pertama lps adalah baris opsional per detik argumen numerik (default: 300)

Catatan: jika nama file hanya numerik, Anda mungkin harus menentukannya dengan path: ./3.

Seperti cat ini dapat meneruskan file yang diberikan sebagai argumen dan / atau input standar

Jadi kita bisa:

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

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

Untuk kesenangan:

export TIMEFORMAT='%R' ;clear ;time seq 1 $((LINES-2)) | ./catLps.pl $((LINES-2))
F. Hauri
sumber
2
yang terlihat seperti voodoo serius yang Anda lakukan di sana. itu sangat keren, saya mencobanya dan berhasil. saya tidak tahu bagaimana Anda melakukannya. apa perl perl pilih? undef? saya bisa mencarinya. luar biasa.
Cris Stringfellow
2
@ ChrisStringfellow Ok, saya telah menambahkan beberapa penjelasan dan menggunakan script lengkap Time::HiRes modul perl untuk akurasi lebih
F. Hauri
Tuhanku. Itu jawaban yang luar biasa. Terima kasih. Saya mencoba membesarkannya untuk kedua kalinya. Saya belajar sesuatu dengan membaca penjelasan Anda yang luar biasa.
Cris Stringfellow
2
Anda dapat meningkatkan komentar saya juga ;-)
F. Hauri
@CrisStringfellow Jawaban diedit: dengan menggunakan -p beralih ke perintah perl, skrip diringankan!
F. Hauri
7

cukup gunakan awk dengan tidur:

awk '{print $0; system("sleep .1");}' log.txt
DMas
sumber
Ini bekerja untuk saya dan untuk situasi saya adalah pilihan terbaik daripada opsi skrip di atas. Tidak yakin mengapa jawaban ini tidak dipilih.
Citizen Kepler
1
Berbeda dengan solusi perl itu cukup mudah dibaca.
Gunslinger
0

Saya terlambat ke pesta, tetapi saya menemukan ini akan menjadi latihan pembelajaran yang berguna untuk dicoba dengan python, jadi saya akan memberikan apa yang saya dapat:

#!/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)

Ia menerima input dari stdin atau sebagai argumen (-i) dan secara default menulis satu baris per 1 / 10th per detik, tetapi itu dapat diubah dengan argumen lain (-d).

Grezzo
sumber