特定の行/秒の速度でファイルをターミナルに転送する

特定の行/秒の速度でファイルをターミナルに転送する

私は怠け者なので、これを行うためのスクリプトを書くこともできますが、それをどのように行うかを考えるのも怠け者です。

私はよく次のようなことをします:

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

実験の長い出力を見るとき、ページをスクロールさせて連続したパターンが形成されて分散するのを見たいことがあります。しかし、100 万行のファイルで cat を使用すると、おそらく 5 秒で終了します。これは私にとっても速すぎます。

「スクロール ユーティリティ」のような、ファイルの表示速度を遅くする方法はありますか? 高速化は必要ですが、1 秒あたり 20 万行は不要です (おそらく、そのすべてはディスプレイに表示されません)。

何かのようなもの

cris$ scroll -lps=300 output.txt

そして、座って 1 秒あたり 300 行が流れていくのを眺めるのが理想的だと思います。

答え1

短くて読める:

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

この解決策は小さくて読みやすいので、コメントとして投稿します。DMasの回答この種の解決策を推進しているようです!

しかし、私はこれが嫌いです。この実行では、perlはフォーク/bin/sleep300倍速/秒まで!

これは大量のリソースを消費します!また、間違った良い解決策!!

使用組み込み寝る

残念ながら、組み込みは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 行 / 秒は、0.0033333333 秒ごとに 1 行を意味します。

  • print引数なしで$_は、デフォルトの入力スペース

  • または... | perl -eと呼ばれる標準入力は、自動的に割り当てられ、... | perl -ne... | perl -pe*STDINデフォルトのファイル記述子は、標準入力から読み取るの<>と同じ動作をします(<STDIN>$/入力レコードセパレータデフォルトでは改行)に到達します。英語では、デフォルトで<>1つ標準入力から行を読み取り、その内容を$_変数に割り当てます。

  • &&そして条件としてではなく、チェーンコマンドセパレーターしたがって、1 行を (正常に) 印刷した後、次のコマンドを実行します。

  • select使わないプログラマーのトリックsleepこのコマンドは、イベントをトラップするように設計されていますファイル記述子(入力および/または出力、ファイル、ソケットおよび/またはネットソケット)。このコマンドを使用すると、プログラムは待って3種類のイベントについて、フィードを読む準備ができました書き込み準備完了のフィードそしてフィードで何らかのイベントが発生しました4 番目の引数は秒単位のタイムアウトなので、構文は次のようになります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)

注意: ファイル名が数字のみの場合は、path: で指定する必要があります./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

awk を sleep 付きで使うだけです:

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

答え3

インタープリターを使用する代わりに、特別に作成されたツールを使用できます。このツールは、おそらくディストリビューションにインストールされているか、自分でインストールできます (apt-get install pv など)。

ファイルを 1 秒あたり 5 行で表示するには:

cat filename | pv --quiet --line-mode --rate-limit 5

ファイルを 1 秒あたり 100 バイトで表示するには:

cat filename| pv --quiet  --rate-limit 100

答え4

Ruby のsleep関数は浮動小数点値をサポートしているので、@F.Hauri の回答に基づいた効率的で短いソリューションを次に示します。

ruby -pe 'sleep 0.00333' log.txt

または

ruby -pe 'sleep (1.0/300)' log.txt

関連情報