File Cat al terminale a una particolare velocità di linee al secondo


15

Sono pigro e potrei scrivere una sceneggiatura per farlo, ma sono anche troppo pigro per pensare a come farlo.

Faccio spesso cose come:

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

A volte, quando guardo il lungo output di un esperimento, mi piace lasciare che la pagina scorra e guardi i modelli successivi formarsi e disperdersi. Ma l'utilizzo di cat su un file con 1 milione di righe termina in circa 5 secondi. Questo è troppo veloce anche per me.

Esiste un modo per rallentare la velocità di visualizzazione del file, qualcosa come un'utilità di scorrimento? Voglio veloce, ma non 200k righe al secondo (il che presumibilmente il display non si sarebbe nemmeno registrato).

Qualcosa di simile a

cris$ scroll -lps=300 output.txt

E poi sedermi e guardare 300 righe al secondo sarebbe l'ideale, immagino.


7
Prova qualcosa del genere cat FILENAME | pv -l -L 900 -q. Il limite è in byte al secondo, non in righe al secondo, quindi sto facendo di questo un commento non una risposta.
David Schwartz,

Ok bene, è una bella utility e funziona in parte. Ma sì, è un po 'instabile poiché va dopo bps non lps.
Cris Stringfellow,

Risposte:


17

Breve e leggibile :

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

Pubblico queste soluzioni perché sono piccole e leggibili, poiché i commenti della risposta di DMas sembrano promuovere questo tipo di soluzione!

Ma io odio questo perché: per questa esecuzione, perl sarà sborsare a /bin/sleep300x / secondi!

Questo è un grande consumatore di risorse! Anche una buona soluzione sbagliata !!

Usando il sonno incorporato in

Sfortunatamente, builtin sleepè limitato a numeri interi. Quindi dobbiamo usare selectinvece:

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

Sotto perl, print while <>potrebbe essere sostituito -pdall'interruttore:

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

Proviamo:

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

Spiegazione:

  • 300 righe / sec significa 1 riga per 0,0033333333 sec.

  • printsenza stampe argomento $_che è spazio di ingresso predefinito .

  • chiamato come ... | perl -e, ... | perl -neoppure ... | perl -pe, l'input standard verrebbe assegnato automaticamente al *STDINquale è il descrittore di file predefinito , quindi <>farebbe lo stesso di quello <STDIN>che verrà letto dall'input standard fino a quando $/(il separatore del record di input che è di default una nuova riga ) verrà raggiunto. In inglese, per impostazione predefinita <>leggerà una riga dall'input standard e assegnerà il contenuto alla $_variabile.

  • &&è una condizione e , ma viene usata lì come separatore di comandi a catena, quindi dopo aver stampato (con successo) una riga, eseguendo il comando successivo.

  • selectè un trucco da programmatore da non usaresleep . Questo comando è progettato per intercettare eventi su descrittori di file (input e / o output, file, socket e / o socket di rete). Con questo comando, un programma può attendere 3 tipi di eventi, feed pronto per la lettura , feed pronto per la scrittura e alcuni eventi si sono verificati nel feed . Il quarto argomento è un timeout in secondi, quindi lo è la sintassi select <feeds where wait for input>, <feeds where having to write>, <feed where something could happen>, <timeout>.

Per una maggiore precisione, è possibile utilizzare il Time::Hiresmodulo perl:

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

Nota: $.è il numero della riga di input corrente .

Meglio scritto come 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 <>

Uso:

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

Il primo argomento lpsè argomento numerico riga al secondo opzionale (impostazione predefinita: 300)

Nota: se il nome del file è solo numerico, potrebbe essere necessario specifiy loro con percorso: ./3.

In catquesto modo potrebbero passare i file forniti come argomento e / o input standard

Quindi potremmo:

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

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

Per divertimento:

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

2
sembra un voodoo serio che stai facendo lì. è così bello, l'ho provato e funziona. non ho idea di come l'abbia fatto però. che diavolo è perl select? undef? posso cercarlo. sorprendente.
Cris Stringfellow,

2
@CrisStringfellow Ok, ho aggiunto alcune spiegazioni e uno script completo usando il Time::HiResmodulo perl per una maggiore precisione
F. Hauri,

mio Dio. Questa è una risposta fantastica. Grazie. Ho provato a votarlo una seconda volta. Sto imparando qualcosa leggendo la tua meravigliosa spiegazione.
Cris Stringfellow,

2
Potresti anche votare i miei commenti ;-)
F. Hauri il

@CrisStringfellow Risposta modificata: con l'uso del -pcomando switch to perl, lo script è stato alleggerito!
F. Hauri,

11

basta usare awk con sleep:

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

Questo ha funzionato per me e per la mia situazione era l'opzione migliore piuttosto che le opzioni di script sopra. Non sono sicuro del motivo per cui questa risposta è sotto votata.
Citizen Keplero

2
A differenza della soluzione perl, è abbastanza leggibile.
Gunslinger,

1
@Gunslinger: la sintassi system(*sleep .1")genererà 10 fork / sec! Questo potrebbe essere scritto perl -pe 'system "sleep .1"' log.txt: anche leggibile, ma molto costoso (non adatto al sistema!)
F. Hauri,

Anch'io preferisco questa risposta leggibile. L'unica cosa è che lancerà il comando shell sleep per ogni linea che emette. Ma essendo una fodera perfettamente leggibile non mi interessa.
itsafire

0

Sono in ritardo alla festa, ma ho scoperto che questo sarebbe un utile esercizio di apprendimento da provare in Python, quindi metterò su quello che ho ottenuto:

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

Accetta input da stdin o come argomento (-i) e per impostazione predefinita scrive una riga per 1/10 di secondo, ma può essere modificata con un altro argomento (-d).


Grazie. Stavo iniziando a sviluppare qualcosa di simile a questa idea in Python quando mi sono imbattuto in questo D&R. Noto che Python supporta anche determinati docs.python.org/3/library/select.html in un modo simile a Perl come usato nella risposta di F. Hauri.
ybull
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.