我想创建一个Perl(或Bash)脚本来动态创建和绘制数据。这意味着我想从日志文件 file.log 中提取数据,理想情况下不要写一个tmp文件(如果它只能用tmp文件,这也没关系)和情节与Gnuplot。随着日志文件的增长,我希望在图中看到其他信息。
有关类似主题,请参阅this question。
对于Perl,我到目前为止的是这个脚本:
#!/usr/bin/perl
use strict;
use warnings;
my $path = "file.log";
my @grepped;
my $switch = "off";
open(INFILE,"< $path") or die $! \n";
while (my $line = <INFILE>) {
if ($line =~ m{^Time = (\d+)}){
push(@grepped,"$1\t");
};
if ($line =~ m{^Errors: local = (\d+), global = (\d+)}){
push(@grepped,"$1\t");
push(@grepped,"$2\n");
$switch = "refresh";
};
if ($switch eq "refresh"){
open(GP, "| gnuplot -persist") or die: $! \n";
print GP << "GNU_EOF";
plot "@grepped" u 2:1
pause 1; refresh; reread;
GNU_EOF
close(GP);
}
}
close(INFILE)};
我的第一个问题是Gnuplot的即时功能无效。当 file.log 发生更改时,Gnuplot图的刷新无效。我不知道-persist
在这里是否正确,或者我是否必须使用replot
选项而不是refresh
。我试过了,但它不适合我。
第二个问题是将数据读入数组 @grepped ,并在一个脚本中的Gnuplot中使用它来更改输入文件。另外一个限制是(从代码中可以看出)gnuplot只有在写入 @grepped 中的完整新行时才应刷新绘图。否则,由于数据分配错误,肯定会发生错误。
当我尝试一个简单的脚本时:
#!/usr/bin/gnuplot -persist
plot "data.dat" u 2:1
pause 1; replot; reread;
或
#!/usr/bin/gnuplot
plot "data.dat" u 2:1
pause 1; refresh; reread;
如果我手动更改data.dat
并保存它,即时部分会有效。
答案 0 :(得分:3)
以下是两种即时绘制数据的方法。
您必须反复调用plot
,数据由外部脚本预处理。最小的gnuplot脚本filter.gp
是:
while (1) {
plot '< ./myscript.pl' using 2:1
pause 1
}
要停止此操作,请点击Ctrl+C
。
预处理的Perl脚本可能类似于以下myscript.pl
:
#!/usr/bin/perl
use strict;
use warnings;
my $path = "file.log";
my @grepped;
my $t = 0;
open(INFILE,"< $path") or die "$! \n";
while (my $line = <INFILE>) {
if ($line =~ m{^Time = (\d+)}){
$t = $1;
};
if ($line =~ m{^Errors: local = (\d+), global = (\d+)}){
print "$t\t$1\t$2\n";
};
};
close(INFILE);
只需使用gnuplot filter.gp
运行它。
为了使其更易于配置,可以更改脚本以使用通过命令行传递给gnuplot的变量:
while (1) {
plot '< ./myscript.pl -f '.path using 2:1
pause 1
}
或使用reread
:
plot '< ./myscript.pl -f '.path using 2:1
pause 1
reread
使用gnuplot -e "path='file.log';" filtermod.gp
调用此脚本。
虽然有效,但会一遍又一遍地过滤整个文件。
这是一个Perl脚本,它基本上适合我,但它是我的第一个真正的Perl脚本,所以可能有一些非理想的部分。随意评论。
#!/usr/bin/perl
use strict;
use warnings;
my $path = "file.log";
my @grepped;
my $switch = "off";
open(my $gp, "| gnuplot -persist") or die "$! \n";
$gp->autoflush(0);
use File::Tail;
my $file = File::Tail->new(name=>$path, maxinterval=>1, tail=>-1);
while (defined(my $line= $file->read)) {
if ($line =~ m{^Time = (\d+)}){
push(@grepped,"$1\t");
};
if ($line =~ m{^Errors: local = (\d+), global = (\d+)}){
push(@grepped,"$1\t");
push(@grepped,"$2\n");
$switch = "refresh";
};
if ($switch eq "refresh") {
print $gp <<"GNU_EOF";
plot '-' using 2:1
@grepped
e
GNU_EOF
$gp->flush;
$switch = "off";
};
Time::HiRes::sleep(0.1);
};
我发现这里重要的是
autoflush
和flush
。sleep
。适用于非常小的测试数据文件。不知道它是否适用于更大的一个,但应该对你有所帮助。