perl脚本在目录中搜索单词

发布于 2025-02-06 14:17:42 字数 109 浏览 1 评论 0原文

我正在寻找一个perl脚本以在目录中的所有文件中grep grop for字符串。

bash命令。 代码: grep -r'word'/path/to/dir

I'am looking for a perl script to grep for a string in all files inside a directory .

bash command .
Code:
grep -r 'word' /path/to/dir

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梦巷 2025-02-13 14:17:42

这是一项相当典型的任务,而我找不到最简单,最简单的简单工具的直接答案,便捷的 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在此处读取文件的方式只是一种方法。它可能不适合极大的文件,因为它一次读取所有行,其中一个更好地逐行阅读。

访问方法基于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测试。


否则,会有用于递归遍历和搜索的库,例如 file :: file :: find :: find :: rule )或 path :: iterator :: ulue

为了完整性,这是核心 file :: find file

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}};
}

This is a fairly canonical task while I couldn't find straight answers with a possibly easiest and simples tool for the job, the handy 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

The way a file is read here, using lines, is just one way to do that. It may not be suitable for extremely large files as it reads all lines at once, where one better read line by line.

The visit method is based on iterator, which accomplishes this task cleanly as well

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 
} 

Here we have to provide a data structure to accumulate information but we get more flexibility.

The -f filetest used above, of a "plain" file, is still somewhat permissive; it allows for swap files, for example, which some editors keep during a session (vim for instance). Those will result in all kinds of matches. To stay with purely ASCII or UTF-8 files use -T test.


Otherwise, there are libraries for recursive traversal and searching, for example File::Find (or File::Find::Rule) or Path::Iterator::Rule.

For completeness, here is a take with the core 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}};
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文