1

我正在尝试将 grep 与变量正则表达式一起使用。我假设以下程序不会打印任何内容,因为正则表达式/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什么?

4

3 回答 3

5

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

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

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

但那很愚蠢。使用正常m//匹配运算符或其变体:

grep /$regex/, @array;

这应该会产生空输出。


引号运算符使编写正则表达式更容易,因为它与orqr//中的普通正则表达式具有相同的解析规则。文字的值是一个正则表达式对象,可以分配给一个变量,然后可以进行插值。这允许像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
于 2013-07-17T22:27:07.380 回答
5

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

这是您可以使用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.

于 2013-07-17T23:20:53.447 回答
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//

于 2013-07-17T22:46:07.800 回答