用于在目录中搜索单词的Perl脚本

2ul0zpep  于 2022-11-15  发布在  Perl
关注(0)|答案(1)|浏览(123)

我正在寻找一个Perl脚本,以grep在目录内的所有文件的字符串。
bash命令。代码:grep -r 'word' /path/to/dir

dphi5xsq

dphi5xsq1#

这是一个相当规范的任务,而我无法找到直接的答案与一个可能是最简单的和最简单的工具的工作,方便的Path::Tiny

use warnings;
use strict;
use feature 'say';

use Data::Dump;  # dd
use Path::Tiny;  # path 

my $dir = shift // '.';

my $pattern = qr/word/;

my $ret = path($dir)->visit( 
    sub { 
        my ($entry, $state) = @_; 
        return if not -f; 
     
        for ($entry->lines) {
            if (/$pattern/) {
                print "$entry: $_";
                push @{$state->{$entry}}, $_;  
            }   
        }   
    },  
    { recurse => 1 } 
); 

dd $ret;  # print the returned complex data structure

这里使用lines读取文件的方式只是其中一种方式。它可能不适合非常大的文件,因为它一次读取所有行,在这种情况下最好逐行读取。
visit方法基于iterator,它也可以干净地完成此任务

my $iter = path($dir)->iterator({ recurse => 1 });

my $info;

while (my $e = $iter->()) { 
    next if not -f $e; 
    
    # process the file $e as needed
    #/$pattern/ and push @{$info->{$e}}, $_ and print "$e: $_" 
    #    for $e->lines 
}

在这里,我们必须提供一个数据结构来积累信息,但我们得到了更多的灵活性。
上面使用的“普通”文件的-f filetest仍然有些宽松;它允许交换文件,例如,一些编辑器在会话期间保留的文件(例如vim)。这些文件将导致所有类型的匹配。要使用纯ASCII或UTF-8文件,请使用-T test。
另外,还有用于递归遍历和搜索的库,例如File::Find(或File::Find::Rule)或Path::Iterator::Rule
为了完整起见,这里是内核File::Find的一个例子

use warnings;
use strict;
use feature 'say';    
use File::Find;

my @dirs = @ARGV ? @ARGV : '.';

my $pattern = qr/word/;

my %res;
find( sub {
        return if not -T;  # ASCII or UTF-8 only

        open my $fh, '<', $_ or do {
            warn "Error opening $File::Find::name: $!";
            return;
        };

        while (<$fh>) { 
            if (/$pattern/) { 
                chomp;
                push @{$res{$File::Find::name}}, $_
            }
        }
    }, @dirs
);

for my $k (keys %res) { 
    say "In file $k:";
    say "\t$_" for @{$res{$k}};
}

相关问题