我从我的一个朋友那里得到了这个代码,但因为我没有使用perl,我不知道它是如何工作的。你能帮我理解吗?
此文件必须获取一个文件,其中包含一些显示延迟的数据,并在间隔内获得累积分布函数。
#!/usr/bin/perl
#print "Starting converter on file $ARGV[0]\n";
if ($#ARGV < 2 || $#ARGV > 3) {
print "Usage: ac_hist_gen.pl <input file> <num intervals> <output file> [ <interval size> ]\n";
exit(-1);
}
open(infile,"$ARGV[0]") || die "Couldn't open $ARGV[0] for reading.\n";
open(outfile,">$ARGV[2]") || die "Couldn't open $ARGV[2] for writing.\n";
for ($i=0; $i< 100 / $ARGV[1]; $i++) {
$dist[$i] = 0;
$acum[$i] = 0;
}
$max=0;
if ($#ARGV == 2) {
while (<infile>) {
if ($_ > $max) {
$max=$_;
}
}
$intsize = $max / $ARGV[1];
} else {
$intsize= $ARGV[3];
}
close(infile);
#print "size is $numpkts, max is $max, div is $intsize , test is $test\n";
open(infile,"$ARGV[0]") || die "Couldn't open $ARGV[0] for reading.\n";
while (<infile>) {
$val = int($_ / $intsize);
if (($_ / $intsize) == $val) {
$dist[$val-1]++;
} else {
$dist[$val]++;
}
# print "val is $val\n";
}
for ($i=0; $i< $ARGV[1]; $i++) {
$limit = ($i+1) * $intsize;
$acum[$i]+= $dist[$i];
$acum[$i+1] = $acum[$i];
print outfile "$limit $acum[$i]\n";
}
close(outfile);
答案 0 :(得分:1)
好的,首先快速讨论一下ARGV。这就像在C程序的main()声明中使用的char ** argv
perl中的ARGV被隐式声明为数组。在perl中,我们引用像这样的整个数组
@ARGV
以及像这样的数组大小
$#ARGV
以及像这样的数组中的单个元素
$ARGV[0]
数组从零开始索引,因此$ARGV[0]
是数组的第一个元素@ARGV
这就是如何读取程序的命令行args,以及所有对ARGV的引用所关注的内容
下一个项目
open(infile,"$ARGV[0]") || die "Couldn't open $ARGV[0] for reading.\n";
open(outfile,">$ARGV[2]") || die "Couldn't open $ARGV[2] for writing.\n";
这是自我记录,考虑到我刚刚与ARGV讨论的内容。这使得一对输入和输出的文件句柄。双引号"
中提到的变量将插值到它们的值。因此,如果$ARGV[0]
是“filename1.txt”,则"ARGV[0]"
将编译为“filename1.txt”
在perl和数组中,也允许使用简单的单值变量(称为标量)
$x=1
与C中的x=1
类似。
但是在perl中,可以在不分配内存的情况下分配字符串。这是自动的。字符串“类型”变量可以简单地转换为数字。一个简单的变量可以从一个数字开始,然后转换为一个字符串,然后根据上下文自动返回一个数字。声明变量也不是强制性的!在C中你必须说int x
来声明它,这在perl中并没有严格执行
下一段代码
for ($i=0; $i< 100 / $ARGV[1]; $i++) {
$dist[$i] = 0;
$acum[$i] = 0;
}
这与C中的完全一样,除了变量前面有一些额外的$符号,并且不需要声明数组的大小@dist和@acum,或者它们的类型
下一点要考虑
while (<infile>) {
if ($_ > $max) {
$max=$_;
}
}
infile
是一个文件句柄,构造<infile>
从文件中读取一行。但是你会注意到,在perl程序中 where 读取数据并不清楚。
这里使用的perl技巧是有一个包含最后读取行的默认变量。变量是$_
。所以这个循环所做的就是在文件中查找最大值。
我现在稍等一下,直到最后
for ($i=0; $i< $ARGV[1]; $i++) {
$limit = ($i+1) * $intsize;
$acum[$i]+= $dist[$i];
$acum[$i+1] = $acum[$i];
print outfile "$limit $acum[$i]\n";
}
这是一个在数组@acum
上执行操作的循环,类似于上面的for
循环
打印行写入输出句柄。如上所述对变量进行插值。
希望这有助于您理解
答案 1 :(得分:1)
你得到的代码编写得不是很好。这是一个修订版本:
#!/usr/bin/perl
# pragmas
use strict;
use warnings;
# read command line arguments
if ($#ARGV < 2 || $#ARGV > 3) {
print "Usage: perl $0 <input file> <num intervals> <output file> [<interval size>]\n";
exit 1;
}
my ($input_file, $num_intervals, $output_file, $interval_size) = @ARGV;
# find interval_size if not specified
unless (defined $interval_size) {
my $max = 0;
process($input_file, sub { $max = $_[0] if $_[0] > $max });
$interval_size = $max / $num_intervals;
}
# fill dist array
my @dist;
process($input_file, sub {
my $q = $_[0] / $interval_size;
my $val = int $q;
$dist[$val == $q ? $val - 1 : $val]++;
});
open my $fh_out, '>', $output_file
or die "cannot open (write) file '$output_file': $!\n";
# fill acum and generate output
my @acum;
for (0 .. $num_intervals - 1) {
my $limit = ($_ + 1) * $interval_size;
$acum[$_] += $dist[$_];
$acum[$_+1] = $acum[$_];
print $fh_out "$limit $acum[$_]\n";
}
close $fh_out;
#
# process 'filename', sub {
# my ($line) = @_;
# # do something with $line, it is chomped
# };
#
sub process {
my ($file, $code) = @_;
open my $fh, '<', $file
or die "cannot open (read) file '$file': $!\n";
local $_;
while (<$fh>) {
chomp;
$code->($_);
}
close $fh;
}
问候,马蒂亚斯
PS:我没有测试代码,但perl -c没问题。