使用perl从目录中的多个文件中查找字符串的最后一次出现

y0u0uwnf  于 2022-12-19  发布在  Perl
关注(0)|答案(2)|浏览(139)

在一个目录中有多个文件。从所有的文件中,我必须找到一个字符串的最后一次出现,并将该行打印到一个result.txt文件中。让我们假设这些文件类似于demo*. txt。
而我要找的字符串是“FREQ”,我试过的代码如下:

for ( glob("demo*.txt"  ) ) {
        my $xm = $_;
        open my $fh, '<', $xm;
        my $pat = "FREQ" ;
        while(my $asa =  <$fh>) {
            my @last = grep(/FREQ/, $asa);
        }
     } 
     print " grep : @last\n";

我试过这个代码,但这给不了什么,我不能找到我正在犯的错误。

qnyhuwrf

qnyhuwrf1#

正如@vkk05所建议的,您需要将use strictuse warnings添加到代码中

use strict;
use warnings;

for ( glob("/tmp/demo*.txt"  ) ) {
    my $xm = $_;
    open my $fh, '<', $xm;
    my $pat = "FREQ" ;
    while(my $asa =  <$fh>) {
        my @last = grep(/FREQ/, $asa);
    }
} 

print " grep : @last\n";

当我跑的时候

Possible unintended interpolation of @last in string at /tmp/fred.pl line 15.
Global symbol "@last" requires explicit package name (did you forget to declare "my @last"?) at /tmp/fred.pl line 15.
Execution of /tmp/fred.pl aborted due to compilation errors.

问题出在my @last行。您在while循环的作用域中定义了@last。这意味着一旦while循环退出,变量@last就会被删除。
@last的定义移到while作用域之外,并将print行移到while循环之后立即运行,将生成以下代码

use strict;
use warnings;

for ( glob("/tmp/demo*.txt"  ) ) {
    my $xm = $_;
    open my $fh, '<', $xm;
    my $pat = "FREQ" ;
    my @last;
    while(my $asa =  <$fh>) {
        @last = grep(/FREQ/, $asa);
    }

    print " grep : @last\n";
}

并且假设测试文件use warnings

$ cat /tmp/demo1.txt 
abc
FREQ 123
FREQ 456

运行该脚本将提供

grep : FREQ 456

最后,在此上下文中使用grep是令人困惑的--它应该在迭代值列表时使用,而不是像本例中那样迭代单个条目。虽然代码可以很好地与您使用grep的方式配合,但是使用grep的更符合perl习惯的解决方案应该是

use strict;
use warnings;

my $pat = "FREQ" ;

for my $xm ( glob("/tmp/demo*.txt"  ) ) {
    open my $fh, '<', $xm
        or die "Cannot open '$xm': $!";

    my @matches = grep { /$pat/ }
                  <$fh>;

    print " file $xm : $matches[-1]\n";
}

注意事项
1.这里在适当的列表上下文中使用grep,与<$fh>沿着遍历文件并匹配包含存储在$pat中的模式的所有行
1.结果存储在@matches中,因此为了获取最后一个结果,print语句使用$matches[-1]@matches中的最后一个条目建立索引。

kmbjn2e3

kmbjn2e32#

如果这是一个一次性的任务,我会使用一个简单的一行程序。
创建四个测试文件。最后一个为空:

echo -e "FREQ\nline 2\nFREQ again\nline4"         > demo1.txt
echo -e "FREQUENT\nline 2 in demo2\nShrek\nXFREQ here" > demo2.txt
echo -e "nothing to see\nnothing to see!"          > demo3.txt 
touch demo4.txt

运行:

perl -E '@f=@ARGV; /FREQ/ and $L{$ARGV}=$_ while<>; print "Last FREQ line in $_: ".($L{$_}//"<none>\n") for @f' demo*.txt | tee result.txt

输出:

Last FREQ line in demo1.txt: FREQ again
Last FREQ line in demo2.txt: XFREQ here
Last FREQ line in demo3.txt: <none>
Last FREQ line in demo4.txt: <none>

相关问题