我正在尝试将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
做什么导致这种情况?
答案 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。