Perl,找到一个匹配项并阅读Perl中的下一行

时间:2018-07-11 05:25:10

标签: perl

我想使用

myscript.pl targetfolder/*

从ASCII文件中读取一些数字。

myscript.pl

@list = <@ARGV>;

# Is the whole file or only 1st line is loaded?

foreach $file ( @list ) {
    open (F, $file);
}

# is this correct to judge if there is still file to load?

while ( <F> ) {
    match_replace()
}

sub match_replace {

    # if I want to read the 5th line in downward, how to do that?
    # if I would like to read multi lines in multi array[row],
    # how to do that?

    if ( /^\sName\s+/ ) {
        $name = $1;
    }               
 }

1 个答案:

答案 0 :(得分:1)

我建议您仔细阅读perlintro-它会为您提供许多您需要的信息。附加评论:

  1. 始终使用strictwarnings。前者将强制执行一些良好的编码习惯(例如声明变量),而后者将告知您潜在的错误。例如,您显示的代码产生的一个警告将是readline() on unopened filehandle F,提示您F当时未打开(更多内容在下面)。

  2. @list = <@ARGV>;:这有点棘手,我不建议您使用-实际上,您正在使用glob,而扩展targetfolder/*是您的shell应该做的事情,如果您使用的是Windows,则建议不要手动进行Win32::Autoglob

  3. foreach ... { open ... }:打开文件后,您将不执行任何操作-从文件读取的循环必须位于foreach内。

  4. “是整个文件还是仅加载了第一行?” open不会从文件中读取任何内容,它只是打开文件并提供了然后需要从中读取文件句柄(您将其命名为F)。

  5. 我强烈建议您使用更现代的三参数形式open并检查错误,并使用词法文件句柄,因为它们的作用域不是全局的,如{{1 }}。

  6. “判断是否还有文件要加载是否正确?” 是的,open my $fh, '<', $file or die "$file: $!";是逐行读取文件的好方法,并且从文件中读取所有内容后,循环将结束。您可能需要使用更明确的形式while (<$filehandle>),以便您的变量具有名称,而不是默认的$_变量-确实会使代码更冗长,但是如果您只是开始可能是一件好事。

  7. while (my $line = <$filehandle>):您没有将任何参数传递给match_replace()。即使这段代码仍然可以“工作”,它还是通过全局变量sub将当前行传递到sub上,但这不是一个好习惯,因为一旦脚本被执行,它将造成混乱并且容易出错。开始变长。

  8. $_:由于您已经命名了if (/^\sName\s+/){$name = $1;} sub,所以我猜您想进行搜索和替换操作。在Perl中,这称为match_replace,您可以在perlrequickperlretut中进行了解。至于您显示的代码,您正在使用s/search/replacement/,但是您的正则表达式中没有任何“捕获组”($1)-您可以在这两个代码中阅读链接。

  9. “如果我想向下阅读第五行,该怎么做?” 与Perl一样,有多种方法可以做到这一点(TIMTOWTDI)。一种方法是使用range operator ..-您可以通过在while循环开始时说(...)来跳过第一行至第四行,这将针对特殊的$.变量测试这些行号,跟踪最近读取的行号。

  10. “,如果我想读取多数组[row]中的多行,该怎么做?” 一种方法是使用push添加当前行行到数组的末尾。由于将文件中的行保留在数组中可能会占用更多的内存,尤其是对于大文件,因此,强烈建议确保您仔细考虑要在此处使用的算法。您尚未解释为什么您想将内容保留在数组中,所以在这里我不能更具体地说明。

这么说了之后,这就是我编写该代码的方式。我使用Data::Dumper添加了一些调试代码-查看脚本正在使用的数据总是很有帮助的。

next if 1..4;

上面的代码明确地在@ARGV上循环并打开每个文件,我在上面确实说过,更详细的代码可以帮助您了解正在发生的事情。我只是想指出Perl的一个不错的功能,即“魔术” #!/usr/bin/env perl use warnings; use strict; use Data::Dumper; # for debugging $Data::Dumper::Useqq=1; for my $file (@ARGV) { print Dumper($file); # debug open my $fh, '<', $file or die "$file: $!"; while (my $line = <$fh>) { next if 1..4; chomp($line); # remove line ending match_replace($line); } close $fh; } sub match_replace { my ($line) = @_; # get argument(s) to sub my $name; if ( $line =~ /^\sName\s+(.*)$/ ) { $name = $1; } print Data::Dumper->Dump([$line,$name],['line','name']); # debug # ... do more here ... } 运算符(在perlop under "I/O Operators"中讨论),它将自动打开<>中的文件并从中读取行。 (只有一小件事,如果我想使用@ARGV变量并让其计算每个文件的行数,则需要使用下面显示的$.块,这在{ {3}}。)这将是编写第一个循环的更“惯用”的方式:

continue