用于处理输入文件的代码段的问题

时间:2011-12-27 19:09:45

标签: perl

我正在研究一个Perl程序,它包含以下用于处理输入文件的段。我不明白s/^\s+//;的用途是什么?而且,什么是'|'和'||'代表open(FILE, "cat $fileName |") || die "could not open file";

open(FILE, "cat $fileName |") || die "could not open file";
while (<FILE>)
{
    s/^\s+//;
    my @line = split;
    if ($line[0]!~ /\:/) {$mark=0}
    my $var = $line[$mark];
       ## some other code
}

3 个答案:

答案 0 :(得分:2)

您可以在perlfunc中阅读各种功能的文档。

此代码将打开一个文件以便通过cat管道的相当谨慎的方式进行读取,而不是简单地打开文件。 |表示shell命令cat通过管道连接到open命令,我们的文件句柄将从输出中读取。

||只是或。打开管道,如果失败,程序就会死掉。

while(<FILE>)将读取输入的每一行,并将每行分配给$_。然后在替换中隐含地使用该行并在下面拆分。即s/^\s+//等于$_ =~ s/^\s+//split等于split(' ', $_)

s/^\s+//

将删除前导空格。拆分将在空白上拆分每一行,元素存储在数组@line中。

由于在空格上使用隐式拆分,因此不需要使用s/^\s+//剥离前导空格,因为这是自动完成的。

如果第一个元素不包含冒号:,则$mark设置为0.否则,它不会被设置,并且可能会使用上一次迭代中的值,因为它不是在循环内定义。最后,$var被初始化为元素编号$mark,其为0或其他。

ETA:作为一个相当阴险的oops:如果$mark未定义,即它不包含冒号,那么$var仍将被分配$line[0],因为undef将被警告转换为0。如果use warnings没有生效,则此错误是无声的,因此是阴险的。

此代码似乎是由对perl不太了解的人编写的,使用它可能不太安全。

答案 1 :(得分:2)

替换修剪出现在行首(whitespace)的前导^,将任何非空白字符留作第一个。

open... || die ...中的|| operator是一个高优先级。如果open失败,则die会执行。

open(FILE, "cat $fileName |")浪费了外部流程。要读取文件以进行输入,只需执行以下操作:

open FILE, '<', $filename or die qq{Could not open "$filename" for reading: $!};

open调用的括号是可选的,因为or没有紧密绑定。

使用词法文件句柄也更好:

open my $fh, '<' $filename or die qq{Could not open "$filename" for reading: $!};

此文件句柄分配给词法变量,该变量仅存在于声明的范围内。程序流退出此范围后,文件将自动关闭。

答案 2 :(得分:0)

部分原因是开发人员正在使用默认变量$_。当你没有在函数中指定变量的名称时,许多Perl命令(我会说约1/3)命令$_。例如,这些在语法上是相同的:

my $uppercase_name = uc($_);
my $uppercase_name = uc;

在这两种情况下,uc函数将以大写字符打印$_变量中的字符串。实际上,即使print语句也使用$_变量。同样,这些都是相同的:

print $_;
print;

在较新的Perl脚本中使用默认变量是不赞成的,因为它不会增加程序的清晰度,也不会使程序更快。我重写了您使用的相同代码段,以便显示丢失的$_变量。它可能使代码更容易理解:

open(FILE, "cat $fileName |") || die "could not open file";
while ($_ = <FILE>)
{
    $_ =~ s/^\s+//;
    my @line = split $_;
    if ($line[0] !~ /\:/) {
        $mark = 0;
    }
    my $var = $line[$mark];
       ## some other code
}

请注意,while语句将读取的行的值放入$_变量,并且替换命令(s/^\s+//)也是在$_变量上运行。我希望能为你澄清一下代码。

现在提出您的问题:

  

_ [W]帽子做'|'和'||'代表什么?

||表示,就像执行这个或那个一样。实际上,可以被认为是if语句:

if (not open(FILE, "cat $fileName |")) {
   die "could not open file";
}

也就是说,如果open语句失败,则执行die语句。如果open语句确实设法打开该文件,则不要执行die语句。

在Perl中,您现在可以看到or而不是||,例如:

open(FILE, "cat $fileName |") or die "could not open file";

这使得含义更加明显:打开文件,或者杀死程序。

文件名末尾的单个管道(|)表示在open语句(cat $filename)中执行该命令,并从该命令的输出中读取。想象一下这样的事情:

open (COMMAND, "java -jar foo.war|") or die "Can't execute 'java -jar foo.war'";

现在,我正在运行命令java -jar foo.war并在我的Perl脚本中使用其输出。

你也可以这样做:

open (MAIL, "|mail $recipient") or die "Can't mail $recipient";
print MAIL "Dear $recipient\n\n";
print MAIL "I hope everything is well.\n";
print MAIL "Sincerely,\n\nDavid";
close MAIL;

我现在打开命令mail $recipient并使用print语句写入它。在这种情况下,我正在通过简单的消息向$recipient发送电子邮件。

  

我不明白什么是s / ^ \ s + //;用于?

在原始程序中,它本身就是一条线:

s/^\s+//;

我添加了缺少变量,这有助于澄清一点:

 $_ =~ s/^\s+//;

这是Perl中的Substitute命令。它取$_变量并用正则表达式^\s+代替。如果你不理解什么是正则表达式,你应该看一下关于这个主题的Perldoc tutorial。基本上,这是从行的开头删除所有空格,制表符和其他形式的空格