我必须维护以下Perl脚本:
#!/usr/bin/perl -w
die "Usage: $0 <file1> <file2>\n" unless scalar(@ARGV)>1;
undef $/;
my @f1 = split(/(?=(?:SERIAL NUMBER:\s+\d+))/, <>);
my @f2 = split(/(?=(?:SERIAL NUMBER:\s+\d+))/, <>);
die "Error: file1 has $#f1 serials, file2 has $#f2\n" if ($#f1 != $#f2);
foreach my $g (0 .. $#f1) {
print (($f2[$g] =~ m/RESULT:\s+PASS/) ? $f2[$g] : $f1[$g]);
}
print STDERR "$#f1 serials found\n";
我几乎知道它的作用,但是如何做到这一点很难理解。对 split()的调用特别令人费解。
这是相当惯用的Perl和如果Perl专家可以就如何做到这一点做出一些澄清建议我将不胜感激,所以如果我需要在输入文件上使用它,它就不能处理,我可以尝试修改它。
它结合了包含测试结果的两个数据记录文件的最佳结果。数据记录文件包含各种序列号的结果,每个序列号的数据以序列号开头和结尾:n(我知道这是因为我的设备创建了输入文件)
我可以描述数据记录文件的格式,但我认为唯一重要的方面是序列号:n ,因为这是所有Perl脚本检查
三元运算符用于从一个输入文件或另一个输入文件打印值,因此输出可以重定向到第三个文件。
答案 0 :(得分:8)
答案 1 :(得分:6)
undef $/
行停用输入记录分隔符。解释器不会一行一行地读取记录,而是在此之后立即读取整个文件。
<>
或'菱形运算符'从命令行或标准输入中读取文件,无论哪个有意义。在您的情况下,命令行被明确检查,因此它将是文件。输入记录分隔已被停用,因此每次看到<>
时,您都可以将其视为将整个文件作为字符串返回的函数调用。
split
运算符使用此字符串并在每次遇到参数中的正则表达式时将其剪切为块。 (?= ... )
构造意味着“分隔符是这样的,但无论如何请将其保留在分块结果中。”
这就是它的全部。总会有一些优化,简化或“其他方法”,但这应该让你运行。
答案 2 :(得分:0)
通过将脚本翻译成java或scala,您可以快速了解脚本的工作原理。 inccode.com转换器提供以下java代码:
public class script extends CRoutineProcess implements IInProcess
{
VarArray arrF1 = new VarArray();
VarArray arrF2 = new VarArray();
VarBox call ()
{
// !/usr/bin/perl -w
if (!(BoxSystem.ProgramArguments.scalar().isGT(1)))
{
BoxSystem.die(BoxString.is(VarString.is("Usage: ").join(BoxSystem.foundArgument.get(0
).toString()).join(" <file1> <file2>\n")
)
);
}
BoxSystem.InputRecordSeparator.empty();
arrF1.setValue(BoxConsole.readLine().split(BoxPattern.is("(?=(?:SERIAL NUMBER:\\s+\\d+))")));
arrF2.setValue(BoxConsole.readLine().split(BoxPattern.is("(?=(?:SERIAL NUMBER:\\s+\\d+))")));
if ((arrF1.length().isNE(arrF2.length())))
{
BoxSystem.die("Error: file1 has $#f1 serials, file2 has $#f2\n");
}
for (
VarBox varG : VarRange.is(0,arrF1.length()))
{
BoxSystem.print((arrF2.get(varG).like(BoxPattern.is("RESULT:\\s+PASS"))) ? arrF2.get(varG) : arrF1.get(varG)
);
}
return STDERR.print("$#f1 serials found\n");
}
}