2013-07-17 64 views
1

我試圖將grep與變量正則表達式一起使用。我認爲下面的程序不會打印任何東西,因爲正則表達式/food/與我的數組中的任何項目都不匹配。當使用或不使用qr時,Perl的grep會給出不同的結果

#!/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做什麼導致這種情況?

回答

6

qr//是一個值,與$_不匹配。正則表達式對象在布爾上下文中始終爲true。

要應用正則表達式,e.g像

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 
+4

我會說它「'qr //'*創建* rege x對象;它不會進行任何匹配,直到通過'=〜'使用該對象。由於在布爾上下文中正則表達式對象是真的,所以grep通過了所有的東西。「 – ysth

3

而是在grep塊使用qr//的代碼,在你$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; 

參考documentation有關qr//運營商是如何運作的。

+0

這和amon說的完全一樣,除了我說得不那麼優雅。 – jreut

5

amon在他answer表示,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

相關問題