请详细了解 grep < strong>< strong>> Perl 这两种方式之间的差异
eval {grep /pattern/, ....};
和正常的,
grep {/pattern/} ....
答案 0 :(得分:3)
首先,您的替代品之间存在2个独立差异,并且它们具有不同的用途。在grep
中包装eval
可以捕获通常致命的错误(如正则表达式中的语法错误)。在grep
关键字后面放置一个块,可以使用比单个表达式更复杂的匹配规则。
以下是您可以从2个示例中进行的4种组合:
@y = grep /pattern/, @x; # grep EXPR, no eval
@y = grep { /pattern/ } @x; # grep BLOCK, no eval
eval { @y = grep /pattern/, @x }; # grep EXPR inside eval BLOCK
eval { @y = grep { /pattern/ } @x }; # grep BLOCK inside eval BLOCK
现在我们可以通过两个不同的问题详细了解:您从eval
获得了什么,以及使用grep BLOCK
语法获得了什么?在上面显示的简单情况中,你不会从任何一个中获得任何东西。
当您想要进行匹配条件比简单正则表达式更复杂的grep
时,grep BLOCK
可让您更灵活地表达条件。您可以在块中放置多个语句并使用临时变量。例如grep中的这个grep:
# Note: not the most efficient method for finding an intersection of arrays.
my @a = qw/A E I O U/;
my @b = qw/A B D O P Q R/;
my @intersection = grep { my $x = $_; grep { $_ eq $x } @b } @a;
print "@intersection\n";
在上面的示例中,我们需要一个临时的$x
来保存外部grep
正在测试的值,以便可以将其与内部$_
中的grep
进行比较。内部grep
可以在没有BLOCK的情况下编写为grep $_ eq $x, @b
,但我认为对两者使用相同的语法看起来更好。
如果您正在查找在运行时确定的正则表达式的匹配项,并且在正则表达式无效时您不希望程序中止,那么eval
块将非常有用。例如:
@x = qw/foo bar baz quux xyzzy/;
do {
print STDERR 'Enter pattern: ';
$pat = <STDIN>;
chomp $pat;
eval {
@y = grep /$pat/, @x;
};
} while($@);
print "result: @y\n";
我们要求用户提供模式并打印@x
的匹配列表。如果模式不是有效的正则表达式,eval
会捕获错误并将其放入$@
,程序将继续运行(&#34;无效&#34;消息将被打印并且循环继续所以用户可以再试一次。)当输入有效的正则表达式时,没有错误,因此$@
为假,结果为&#34;线打印。样品运行:
Enter pattern: z$
result: baz
Enter pattern: ^(?!....)
result: foo bar baz
Enter pattern: ([^z])\1
result: foo quux
Enter pattern: [xyz
Invalid pattern
Enter pattern: [xyz]
result: baz quux xyzzy
Enter pattern: ^C
请注意eval
在固定的regexp中没有捕获语法错误。这些是在编译脚本时编译的,所以如果你有一个像
perl -ne 'print if eval { /[xyz/ } or eval { /^ba/ }'
立即失败。 eval
没有帮助。与
perl -ne '$x = "[xyz"; $y = "^ba"; print if eval { /$x/ } or eval { /$y/ }'
这是同样的事情,但是使用从变量构建的正则表达式 - 这个运行并打印/^ba/
的匹配项。第一个eval
始终返回false(并设置$@
,如果您不看它,这并不重要。