如何在Perl中实现Unix的grep
?我尝试使用Perl的内置grep
。这是无效的代码:
$pattern = @ARGV[0];
$file= @ARGV[1];
open($fp,$file);
@arr = <$fp>;
@lines = grep $pattern, @arr;
close($fp);
print @lines;
顺便说一下,我只尝试基本的grep
功能不全功能,其次我不想自己进行字符串解析。我想使用内置的grep
或Perl的一些功能。
提前致谢:)
答案 0 :(得分:13)
在Perl中引用整个数组,我们使用@
。但是为了引用标量的各个元素,我们使用$
。
因此,您需要在这些行上使用$
而不是@
:
$pattern = @ARGV[0];
$file= @ARGV[1];
另外
此
@lines = grep $pattern, @arr;
应该是
@lines = grep /$pattern/, @arr;
Perl中的grep具有以下通用语法:
grep EXPR,LIST
它评估EXPR
的每个元素的LIST
,并返回由表达式求值为true的元素组成的列表值。
您的EXPR
正在搜索数组$pattern
中的模式@arr
。要搜索您需要使用/PATTERN/
而不使用/
字符串$pattern
将被评估为true或false。
答案 1 :(得分:13)
当然,codaddict的答案是对的,但我想补充一些评论:
您应始终使用以下两行开始编写脚本:
use strict;
use warnings;
使用三个args打开并测试错误:
open my $fh, '<', $file or die "unable to open '$file' for reading : $!";
由于use strict
,你必须声明所有变量。所以你的脚本就像:
#!/usr/bin/perl
use strict;
use warnings;
my $pattern = $ARGV[0];
my $file = $ARGV[1];
open $fh, '<', $file or die "unable to open file '$file' for reading : $!";
my @arr = <$fh>;
close $fh; # close as soon as possible
my @lines = grep /$pattern/, @arr;
print @lines;
如果您的文件很大,您可以避免在内存中完全读取它:
#!/usr/bin/perl
use strict;
use warnings;
my $pattern = qr/$ARGV[0]/;
my $file= $ARGV[1];
print "pattern=$pattern\n";
my @lines;
open my $fh, '<', $file or die "unable to open file '$file' for reading : $!";
while(my $line=<$fh>) {
push @lines, $line if ($line =~ $pattern);
}
close($fh);
print @lines;
答案 2 :(得分:13)
由于您已经接受了答案,我正在撰写此答案以供将来读者寻找类似问题的参考,但不完全是您的:
正如人们已经回答的那样,使用perl模拟grep的方法是使用在线方法。 对于使用perl作为'更好'的grep(以及查找和剪切......),我推荐书minimal perl,你很幸运,因为'perl as a "better" grep'的章节是示例章节之一。
这里有更多来自本书的例子:
perl -wnle '/foo/ and print' null.txt # normal grep
perl -wnle '/foo/ and print "$ARGV: $_"' null.txt # grep -H
perl -wnle '/foo/ and print $ARGV and close ARGV' null_1.txt null_2.txt # grep -l
在最后一个示例中,ARGV是当前文件句柄,与-l一样,您有兴趣查找具有匹配项的文件,您可以打印文件名,并在文件中第一次匹配后转到下一个文件。
您也可以按行搜索:
$ perl -00 -wnl -e '/\bBRIBE\b/i and print;' SenQ.testimony
I knew I'd be in trouble if
I ACCEPTED THE BRIBE!
So I did not.
My minimum bribe is $100k, and she only offered me $50k,
so to preserve my pricing power, I refused it.
或者只找到第一场比赛:
$ perl -00 -wnl -e '/\bBRIBE\b/i and close ARGV;' SenQ.testimony
I knew I would be in trouble if
I ACCEPTED THE BRIBE!
So I did not.
最后如果你问grep和perl,我想我应该提到ACK。它在perl中实现了grep功能并对其进行了扩展。这是一个很棒的工具,作为一个加分,你可以把它作为一个CPAN包。我总是使用命令行,我不知道你是否可以直接从你的perl程序访问它的方法,但这将是非常好的。
答案 3 :(得分:11)
您可以直接在命令行上逼近grep
的原始版本。 -e
选项允许您在命令行上定义Perl脚本。 -n
选项大致包含您的脚本:while (<>){ SCRIPT }
。
perl -ne 'print if /PATTERN/' FILE1 FILE2 ...
稍微好一点的grep
近似值将在每个打印的匹配前面添加文件名前缀。请注意,此示例与上面的示例一样,不会经历打开任何文件的麻烦。相反,我们使用Perl的<>
构造来遍历所有文件,$ARGV
变量提供当前文件名。
use strict;
use warnings;
my $pattern = shift;
while (my $line = <>){
print $ARGV, ':', $line if $line =~ $pattern;
}
答案 4 :(得分:4)
基本的“grep”功能已经实现。 (=〜)
$string =~ /pattern/;