当使用或不使用qr时,Perl的grep给出不同的结果

时间:2013-07-17 22:24:29

标签: regex perl grep

我正在尝试将grep与变量regex一起使用。我假设以下程序什么都不打印,因为正则表达式/food/与我的数组中的任何项都不匹配。

#!/usr/bin/perl

use strict;
use warnings;

use feature 'say';

my @arry = qw/foo bar baz/;
my $regex = "food";

say join ",", grep { qr/$regex/ } @arry;

但输出说不然:

foo,bar,baz

当我拿出qr时,我得到了我预期的结果(即没有匹配)。 qr做什么导致这种情况?

3 个答案:

答案 0 :(得分:5)

qr//是一个值,与$_不匹配。在布尔上下文中,正则表达式对象始终为true。

您想要应用正则表达式,例如

grep $_ =~ qr/$regex/, @array;

但这很愚蠢。使用普通m//匹配运算符或其变体:

grep /$regex/, @array;

然后应该产生空输出。


qr//引用运算符使组合正则表达式更容易,因为它与m//s///中的普通正则表达式具有相同的解析规则。 qr//文字的值是一个正则表达式对象,可以将其赋值给变量,然后可以进行插值。这允许像

这样的代码
my $foobarbaz = qr/\s*(?:foo|bar|baz)\s*/; # not regexp parsing rules at work for \s
local $_ = "bar  foo baz";
say m/${foobarbaz}{2,}/ ? 1 : 0; # use this to compose a regex

答案 1 :(得分:5)

正如amon在他的answer中所说,qr//构造创建了一个永远不会为假的正则表达式对象,因此使用grep { qr/anything/ } @arry选择数组中的所有内容。 / p>

这是你使用qr正则表达式的方法:

#!/usr/bin/perl

use strict;
use warnings;

use feature 'say';

my @arry = qw/foo bar baz dog food/;
my $regex = "food";
my $qr = qr/$regex/;

say "[", join ",", grep({ qr/$regex/ } @arry), "]"; # Original
say "[", join ",", grep({ $_ =~ $qr  } @arry), "]"; # Modified
say $qr;                                            # Stringized

输出正如您所期望的那样:

[foo,bar,baz,dog,food,]
[food,]
(?^:food)

必须使用括号来限制grep的范围(否则,"]"将作为额外参数传递给grep,而不是say

答案 2 :(得分:3)

不要在qr//块中使用grep,而是在$regex变量的定义中使用它。由于qr//是一个值(特别是编译的正则表达式),它实际上并不会尝试匹配任何内容。由于您已将qr//放在布尔上下文中,因此它始终为true

像这样使用普通m//运算符可能更容易:grep /$regex/, @arry;

如果出于某种原因,您确实希望在对阵列使用grep之前使用预编译的正则表达式,请尝试使用。

#!/usr/bin/perl

use strict;
use warnings;

use feature 'say';

my @arry = qw/foo bar baz/;
my $regex = qr/food/;

say join ",", grep { /$regex/ } @arry;

有关qr//运算符如何工作的一些示例,请参阅documentation