2017-10-13 99 views
4

當我使用捕獲組創建regex變量時,整個匹配成功,但捕獲組爲NilPerl 6正則表達式變量和捕獲組

my $str = 'nn12abc34efg'; 
my $atom =/\d ** 2 /; 
my $rgx =/($atom) \w+ ($atom) /; 

$str ~~/$rgx/; 
say ~$/; # 12abc34 
say $0; # Nil 
say $1; # Nil 

如果我修改程序,以避免$rgx,一切正常:

my $str = 'nn12abc34efg'; 

my $atom =/\d ** 2 /; 
my $rgx =/($atom) \w+ ($atom) /; 

$str ~~/($atom) \w+ ($atom) /; 
say ~$/; # 12abc34 
say $0; # 「12」 
say $1; # 「34」 
+2

有趣的問題。我不確定爲什麼會發生這種情況,但是您可以使用例如「$ rgx」作爲命名正則表達式。 '我的正則表達式rgx {($ atom)\ w +($ atom)}'。然後在'$ str〜/ /'之後,我們會有 '$ [0]'代表第一個捕獲組(例如)。 –

+1

另請參見[如何插入變量到Perl 6正則表達式?](https://stackoverflow.com/q/40883160/2173773) –

+0

謝謝!不知道名爲正則表達式。 –

回答

5

與您的代碼,編譯器提供了以下警告:

Regex object coerced to string (please use .gist or .perl to do that) 

這告訴我們什麼是錯誤的 - 正則表達式不應被視爲字符串。有兩種更適合嵌套正則表達式的方法。首先,你可以包括斷言中的子正則表達式(<>):

my $str = 'nn12abc34efg'; 
my Regex $atom =/\d ** 2 /; 
my Regex $rgx =/(<$atom>) \w+ (<$atom>) /; 
$str ~~ $rgx; 

請注意,我不匹配/ $rgx /。這是把一個正則表達式放在另一個裏面。只需匹配$rgx即可。

更好的方法是使用命名的正則表達式。定義​​和正則表達式如下會讓你訪問比賽團體爲$<atom>[0]$<atom>[1]

my regex atom { \d ** 2 }; 
my $rgx =/<atom> \w+ <atom> /; 
$str ~~ $rgx; 
+1

謝謝你的完美答案!我對p6正則表達式的理解,尤其是'<>'的使用是比較模糊的。 –

+1

@evb很高興我幫了忙。我實際上不知道爲什麼原始代碼不起作用。我推測這是因爲三個正則表達式是如何組成的,我想知道是否正在設置匹配組,然後取消設置嵌套正則表達式匹配。也許這是一個rakudo錯誤,因爲嵌套並不會在其他兩個變體中取消匹配。但是編譯器警告我們的事實讓它在我的書中脫穎而出。 – piojo

+0

我用'(<$atom>)'試過了你的第二個解決方案,它仍然不起作用 - '$ 0'和'$ 1'都是'Nil'。 –

4

的關鍵發現是,$str ~~/$rgx /;是「正則表達式的正則表達式裏面」一個。 $rgx匹配,因爲它應該在它自己的Match對象中設置$0$1,但是隨後在周圍的匹配對象內沒有存儲該信息的地方,所以您看不到它。也許這是清楚的例子,試試這個:

my $str = 'nn12abc34efg'; 
my $atom =/\d ** 2 /; 
my $rgx =/($atom) \w+ ($atom) /; 

$str ~~/$0=$rgx /; 
say $/; 

請注意$0的內容。或者作爲另一個例子,我們給它一個專用名稱:

my $str = 'nn12abc34efg'; 
my $atom =/\d ** 2 /; 
my $rgx =/($atom) \w+ ($atom) /; 

$str ~~/$<bits-n-pieces>=$rgx /; 
say $/; 
+1

謝謝!是的,我注意到第一個變體中的$ 0。 所以,問題是沒有合適的匹配對象... –