1

我正在使用 perl grep,如下例所示。“bfh”是打开命令创建的用于读取的文件句柄。

 @searchResults = grep {/,\s*${searchRecId}\s*,\s*${searchSwId}\s*/} <$bfh>;

代替文件句柄“bfh”,我可以直接给出带有路径的文件名,比如 unix grep 命令吗?如果我想这样做,我需要做出什么改变?下面的代码是否正确?

@searchResults = grep {/,\s*${searchRecId}\s*,\s*${searchSwId}\s*/} /tmp/test.out

我不想给文件句柄或数组。我只想像 unix grep 命令那样做。

将跨越 1000 个文件。当我读取 100000 行文件时,每行涉及 grep 时,我都希望直接获得文件名,而不是打开 1000 个文件句柄并在哈希图中维护。

4

2 回答 2

3

你可以通过map. *.dat例如,这截断了当前目录中的greps :

my @searchResults = grep {
    /,\s*${searchRecId}\s*,\s*${searchSwId}\s*/
} map {
    sub {
        my @ret;
        if (open my $fh, "<", shift) {
            @r = <$fh>;
            close @fh;
        }
        return @ret;
    }->($_);
} glob "*.dat";

但是,在处理多行文件时,这是一种次优方法!这是做同样事情的一种较少内存贪婪的方式:

my @searchResults;
opendir(my $dh, '.') or die "error opening current directory: $!";
while (my $file = readdir $dh) {
    next unless -f $file;
    next if $file !~ /\.dat$/;
    if (open my $fh, '<', $file) {
        while (my $line = <$fh>) {
            if (/,\s*${searchRecId}\s*,\s*${searchSwId}\s*/) {
                push @searchResults, $line;
            }
        }
        close $fh;
    } else {
        die "error processing $file: $!";
    }
}
closedir $dh;

而且,如果您使用 shell,请查看ack实用程序。

于 2012-12-05T12:42:10.680 回答
1

你可以这样做:

use Slurp;
my $filename = 'my/file/name';
@searchResults = grep {/,\s*${searchRecId}\s*,\s*${searchSwId}\s*/}
                   slurp $filename;

不过,这会将文件读入内存。

于 2012-12-05T12:36:20.210 回答