Cat文件以特定的每秒线速度传输到终端


15

我很懒,我可以写一个脚本来做到这一点,但是我什至懒得想怎么做。

我经常做类似的事情:

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

有时,当观察一个实验的长输出时,我喜欢让页面滚动并观看连续的模式形成并散布。但是,在具有100万行的文件中使用cat可能需要5秒钟才能完成。即使对我来说,这也太快了。

有什么办法可以减慢查看文件的速度,例如“滚动实用程序”?我想要快速,但每秒不希望有200k行(所有这些大概都根本无法注册)。

就像是

cris$ scroll -lps=300 output.txt

我想,然后坐下来观看每秒300行的滚动将是理想的。


7
尝试类似的东西cat FILENAME | pv -l -L 900 -q。限制以每秒字节数为单位,而不是以每秒行数为单位,因此,我将其设为注释而不是答案。
大卫·史瓦兹

好吧,那是一个很酷的实用程序,并且部分起作用。但是,是的,这有点混乱,因为它是在bps之后而不是lps之后。
Cris Stringfellow 2012

Answers:


17

简短易读

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

我发布此解决方案是因为它们很小且易于阅读,因为DMas答案的注释似乎促进了这种解决方案!

但是我讨厌这个,因为:对于此运行,perl将分叉/bin/sleep300x /秒!

这是一个很大的资源消耗者!也是一个错误的好的解决方案

使用内置睡眠

不幸的是,内置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,标准输入将automaticaly分配到*STDIN这是默认的文件描述符,所以<>会做同样的<STDIN>,这将从标准输入读取,直到$/输入记录分隔符默认情况下是一个换行符)将达到。在英语中,默认情况下<>会读一个从标准输入和分配内容系$_变量。

  • &&and条件,但在那里用作链命令分隔符,因此(成功)打印一行后,执行下一条命令。

  • select程序员不使用的技巧sleep。此命令旨在捕获文件描述符(输入和/或输出,文件,套接字和/或网络套接字)上的事件。使用此命令,程序可以等待 3种事件,即feed可以读取feed可以写入以及feed上发生了一些事件。第四个参数是超时(以秒为单位),因此语法为select <feeds where wait for input>, <feeds where having to write>, <feed where something could happen>, <timeout>

为了获得更高的精度,您可以使用Time::Hiresperl模块:

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)

注意:如果filename仅是数字,则可能必须使用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
看起来像是您在这里做的一些严重的伏都教徒。太酷了,我尝试了一下,而且效果很好。我不知道你怎么做到的。perl选择什么呢?未定义?我可以查一下。惊人。
Cris Stringfellow

2
@CrisStringfellow好的,我使用Time::HiResperl模块添加了一些解释和完整脚本,以提高准确性
F. Hauri 2012

天哪。这是一个了不起的答案。谢谢。我尝试第二次投票。通过阅读您的精彩解释,我正在学习一些知识。
Cris Stringfellow

2
您也可以支持我的评论;-)
F. Hauri 2012

@CrisStringfellow答案编辑:通过使用-p切换到perl命令,脚本被减轻了!
F. Hauri

11

只需在睡眠中使用awk:

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

这对我有用,对我而言,这是最好的选择,而不是上面的脚本选项。不确定为什么这个答案被否决。
公民开普勒

2
与perl解决方案不同,它具有很好的可读性。
Gunslinger '18

1
@Gunslinger:语法system(*sleep .1")将生成10个fork /秒!可以这样写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/10秒写入一行,但是可以用另一个参数(-d)进行更改。


谢谢。当我碰到这个Q&Ad时,我开始用Python开发类似于这个想法的东西。我注意到Python还支持select docs.python.org/3/library/select.html,类似于F. Hauri的答案中所使用的Perl。
ybull
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.