標(biāo)題
Synopsis 5: Regexes and Rules
版本
創(chuàng)建于: 2002/06/24
上次修改: 2015/05/12
版本: 180
不論何時(shí), 在 grammar
中引用遞歸模式時(shí), 通常更偏好使用 token
和 rule
, 而不是 regex
.
概覽
作為常規(guī)表達(dá)式記法的擴(kuò)展, Perl 6 原生地實(shí)現(xiàn)了 Parsing Expression Grammars
(PEGs). PEGs 要求你為有歧義的那部分提供一個(gè) 主從秩序
. Perl 6 的 主從秩序
由一個(gè)多級(jí)的平局擇優(yōu)法測(cè)試決定:
1) Most-derived only/proto hides less-derived of the same name
2) 最長(zhǎng) token 匹配: food\s+ beats foo by 2 or more positions
3) 最長(zhǎng)字面值前綴: food\w* beats foo\w* by 1 position
4) 對(duì)于一個(gè)給定的 proto, multis from a more-derived grammar win
5) 在一個(gè)給定的編譯單元中, 出現(xiàn)較早的備選分支或 multi 勝出.
#3
會(huì)把任何初始的字面序列當(dāng)作最長(zhǎng)字面值前綴. 如果在最長(zhǎng) token 匹配中有一個(gè)嵌入的備選分支, 那些備選分支會(huì)擴(kuò)展字面值前綴, 把備選分支也作為字面值的一部分. 如果所有的備選分支都是字面值的, 那么字面值也能延伸到備選分支的末尾, 當(dāng)它們重新聚合時(shí). 否則, 備選分支的末尾會(huì)終止所有的最長(zhǎng)字面值前綴, 即使分支全部是字面值的. 例如:
/ a [ 1 | 2 ] b / # 最長(zhǎng)字面值是 'a1b' 和 'a2b'
/ a [ 1 | 2\w ] b / # 最長(zhǎng)文字是'a1 和 'a2', \w 不是字面值
/ a <[ 1 2 ]> b / # 最長(zhǎng)字面值是 'a'
注意, 這種情況下, 字符類(lèi)和備選分支被不同地對(duì)待. 在字符類(lèi)中包含一個(gè)最長(zhǎng)的字面字符串太普遍了.
就像最長(zhǎng) token 匹配一樣, 最長(zhǎng)字面值前綴貫穿于 subrules 中. 如果 subrule 是一個(gè) protoregex, 它會(huì)被看作帶有 |
的備選分支, 后面跟著擴(kuò)展或終止最長(zhǎng)字面值前綴的同一個(gè) rules.
除了這個(gè)主從秩序以外, 如果任何 rule 選擇于主從秩序回溯之下, 那么選擇下一個(gè)最好的 rule. 即, 主從秩序決定了候選者列表; 正是因?yàn)檫x擇一個(gè)候選者并不意味著放棄其它候選者. 然而, 能通過(guò)一個(gè)恰當(dāng)?shù)幕厮菘刂骑@式地放棄其它候選者(有時(shí)叫它 cut
操作符, 但是 Perl 6 有多個(gè) cut , 取決于你想切掉多少)
還有, 任何在 #1
下被選中執(zhí)行的 rule 可以選擇委托給它的祖先來(lái)執(zhí)行; PEG 不對(duì)此回溯.
新的匹配結(jié)果和捕獲變量
附屬的匹配對(duì)象現(xiàn)在可通過(guò) $/
變量獲取, 它隱式是詞法作用域的. 通過(guò)這個(gè)變量來(lái)訪問(wèn)最近一次的匹配. 單獨(dú)的捕獲變量(例如 $0
, $1
等) 正是 $/
中的元素.
順便說(shuō)一下, 不像 Perl 5, Perl 6 中的捕獲變量現(xiàn)在從 $0
開(kāi)始編號(hào)而不是 $1
. 查看下面.
為了檢測(cè) Perl 5的不相關(guān)的 $/
變量的意外使用, Perl 6 的 $/
變量不能被直接賦值.
$/ = $x; # 不支持使用 $/ 變量作為輸入記錄分隔符 (input record separator)
$/ := $x; # OK, 綁定
$/ RR= $x; # OK, 元操作符
($/) = $x; # OK, 列表賦值
沒(méi)變的語(yǔ)法特性
下面的正則特性語(yǔ)法和 Perl 5 是一樣的:
- 捕獲:
(…)
- 重復(fù)量詞:
*
,+
, 和?
- 備選分支:
|
- 反斜線轉(zhuǎn)義:
\
- 最少匹配后綴:
??
,*?
,+?
雖然 |
的語(yǔ)法沒(méi)有變, 但是默認(rèn)的語(yǔ)義稍微改變了一點(diǎn). 我們?cè)噲D混合一個(gè)令人滿(mǎn)意的描述性的和程序上的匹配, 以至于我們能擁有其中兩者. 簡(jiǎn)言之, 你不用給 grammar 寫(xiě)你自己的 tokener
了, 因?yàn)?Perl 會(huì)幫你寫(xiě)好. 查看下面的 Longest-token
匹配.
S05-metasyntax/longest-alternative.t lines 6–52
use v6;
use Test;
plan 53;
#L<S05/Unchanged syntactic features/"While the syntax of | does not change">
my $str = 'a' x 7;
{
ok $str ~~ m:c(0)/a|aa|aaaa/, 'basic sanity with |';
is ~$/, 'aaaa', 'Longest alternative wins 1';
ok $str ~~ m:c(4)/a|aa|aaaa/, 'Second match still works';
is ~$/, 'aa', 'Longest alternative wins 2';
ok $str ~~ m:c(6)/a|aa|aaaa/, 'Third match still works';
is ~$/, 'a', 'Only one alternative left';
ok $str !~~ m:c(7)/a|aa|aaaa/, 'No fourth match';
}
# now test with different order in the regex - it shouldn't matter at all
#?niecza skip 'Regex modifier g not yet implemented'
{
ok $str ~~ m:c/aa|a|aaaa/, 'basic sanity with |, different order';
is ~$/, 'aaaa', 'Longest alternative wins 1, different order';
ok $str ~~ m:c/aa|a|aaaa/, 'Second match still works, different order'; # c -> 從上次匹配結(jié)束的位置匹配繼續(xù)匹配
is ~$/, 'aa', 'Longest alternative wins 2, different order';
ok $str ~~ m:c/aa|a|aaaa/, 'Third match still works, different order';
is ~$/, 'a', 'Only one alternative left, different order';
ok $str !~~ m:c/aa|a|aaaa/, 'No fourth match, different order';
}
{
my @list = <a aa aaaa>;
ok $str ~~ m/ @list /, 'basic sanity with interpolated arrays';
is ~$/, 'aaaa', 'Longest alternative wins 1';
ok $str ~~ m:c(4)/ @list /, 'Second match still works';
is ~$/, 'aa', 'Longest alternative wins 2';
ok $str ~~ m:c(6)/ @list /, 'Third match still works';
is ~$/, 'a', 'Only one alternative left';
ok $str !~~ m:c(7)/ @list /, 'No fourth match';
}
簡(jiǎn)化的模式詞法解析
不像傳統(tǒng)的正則表達(dá)式那樣, Perl 6 不要求你記住數(shù)量眾多的元字符. 相反, Perl 6 通過(guò)一個(gè)簡(jiǎn)單的 rule
將字符進(jìn)行了分類(lèi). 在正則表達(dá)式中, 所有根字符為下劃線(_
)或擁有一個(gè)以 L
(例如, 字母) 或 N
(例如, 數(shù)字)開(kāi)頭的 Unicode 類(lèi)別的字形(字素) 總是字面的.(例如, 自己和自己匹配的). 它們必須使用 \
轉(zhuǎn)義以使它們變成元語(yǔ)法的(這時(shí)單個(gè)字母數(shù)字字符本身是元語(yǔ)法的, 但是任何在字母數(shù)字后面緊緊跟隨的字符不是).
所有其它的字形 — 包括空白符 — 正好與此相反:它們總是被認(rèn)為是元語(yǔ)法的.(例如, 自身和自身不匹配), 必須被轉(zhuǎn)義或引用以使它們變?yōu)樽置嬷? 按照傳統(tǒng), 它們可以使用 \
單獨(dú)轉(zhuǎn)義, 但是在 Perl 6中, 它們也能像下面這樣被括起來(lái).
把一個(gè)或多個(gè)任意類(lèi)型的字形序列放在單引號(hào)中能使它們變?yōu)樽置嬷?(如果使用和當(dāng)前語(yǔ)言相同的插值語(yǔ)義, 雙引號(hào)也是允許的 ) 引號(hào)創(chuàng)建了一個(gè)能量化的原子, 所以,
S05-metasyntax/single-quotes.t lines 16–27
moose*
量詞只作用在字母 e
上, 并匹配 mooseee
, 而
'moose'*
量詞作用在整個(gè)字符串上并匹配 moosemoose
.
下面有個(gè)表格總結(jié)了這些區(qū)別:
字母數(shù)字的 非字母數(shù)字的 混合的
Literal glyphs a 1 _ \* \$ \. \\ \' K\-9\!
Metasyntax \a \1 \_ * $ . \ ' \K-\9!
Quoted glyphs 'a' '1' '_' '*' '$' '.' '\\' '\'' 'K-9!'
換句話(huà)說(shuō), 標(biāo)識(shí)符字形是字面值的(或者在被轉(zhuǎn)義時(shí)是元語(yǔ)法的), 非標(biāo)識(shí)符字形是元語(yǔ)法的(或者在被轉(zhuǎn)義時(shí)是字面值的), 而且單引號(hào)包圍起來(lái)的東西是字面值的烛占。
注意, 目前在 Perl 6 中不是所有的非標(biāo)識(shí)符字形作為元語(yǔ)法都是有意義的(例如 \1
已日、\_
敏弃、-
币砂、!
)。更準(zhǔn)確地說(shuō), 所有非轉(zhuǎn)義的非標(biāo)識(shí)符字形都有可能是元語(yǔ)法的, 而且留作將來(lái)之用匆背。如果你使用了這樣一個(gè)序列, 那么編譯器會(huì)拋出一個(gè)有用的編譯時(shí)錯(cuò)誤以標(biāo)示你要么需要引起這個(gè)序列, 要么定義一個(gè)新的操作符以識(shí)別它卡啰。
S05-metasyntax/unknown.t lines 6–48
分號(hào)字符被特別地保留作非意義(non-meaningful)元字符; 如果看到了未被引起的分號(hào), 那么編譯器就會(huì)抱怨那個(gè)正則表達(dá)式?jīng)]有終止符腔丧。
S05-metasyntax/regex.t lines 73–129
修飾符
-
/x
語(yǔ)法擴(kuò)展不在需要了.. 在 Perl 6 中/x
是默認(rèn)的了.(事實(shí)上, 這是強(qiáng)制的 -- 唯一能用回舊語(yǔ)法的方式是使用:Perl5/:P5
修飾符)
S05-modifier/perl5_4.t lines 7–119
S05-modifier/perl5_2.t lines 7–119
S05-modifier/perl5_9.t lines 7–112
S05-modifier/perl5_1.t lines 7–119
S05-modifier/perl5_8.t lines 7–128
S05-modifier/perl5_5.t lines 7–126
S05-modifier/perl5_7.t lines 7–119
S05-modifier/perl5_6.t lines 7–130
S05-modifier/perl5_3.t lines 7–119
S05-modifier/perl5_0.t lines 9–113
- 沒(méi)有
/s
或/m
修飾符了(變成了元字符來(lái)替代它們-看下面.) - 沒(méi)有
/e
求值修飾符用于替換了, 相反, 使用:
s/pattern/{ doit() }/
或:
s[pattern] = doit()
代替 /ee
的是:
s/pattern/{ EVAL doit() }/
或:
s[pattern] = doit().EVAL
- 修飾符現(xiàn)在作為副詞放在匹配或替換的開(kāi)頭:
m:g:i/\s* (\w*) \s* ,?/;
每個(gè)修飾符必須以自己的冒號(hào)開(kāi)始. 必須使用空格把模式分隔符和最后一個(gè)修飾符隔開(kāi), 如果它會(huì)被看作為前面那個(gè)修飾符的參數(shù).(只有當(dāng)下一個(gè)字符是左圓括號(hào)時(shí)才為真).
- 單字符修飾符也有更長(zhǎng)的版本:
:i :ignorecase 忽略大小寫(xiě)
:m :ignoremark 忽略記號(hào)
:g :global 全局
:r :ratchet 回溯
-
:i
(或:ignorecase
) 修飾符在詞法作用域但不是它的動(dòng)態(tài)作用域中忽略大小寫(xiě). 即, subrules 總是使用它們自己的大小寫(xiě)設(shè)置. 大小寫(xiě)轉(zhuǎn)換的次數(shù)取決于當(dāng)前上下文. 在字節(jié)和代碼點(diǎn)模式中, 要求級(jí)別為1 的大小寫(xiě)轉(zhuǎn)換. 在字形模式下, 需要級(jí)別為 2 的大小寫(xiě)轉(zhuǎn)換.
S05-modifier/ignorecase.t lines 24–87
-
:ii
(或:samecase
) 變體可能被用在替換上以把被替換掉的字符串的大小寫(xiě)模式修改成和匹配字符串的大小寫(xiě)模式一樣。它暗示著該修飾符和上面的:i
修飾符的語(yǔ)義擁有相同的模式刑然。所以把:i
和:ii
放在一塊沒(méi)有必要寺擂。
如果模式匹配的時(shí)候沒(méi)有使用
:sigspace
修飾符, 那么 case info is carried across on a character by character basis. 如果右側(cè)字符串比左側(cè)字符串長(zhǎng), 那么最后一個(gè)字符的大小寫(xiě)被重復(fù)。 如果可能的話(huà), 不管結(jié)果字母是不在單詞的開(kāi)頭, 都會(huì)執(zhí)行單詞首字母大寫(xiě); 如果沒(méi)有可用的單詞首字母大寫(xiě)字符, 就會(huì)使用對(duì)應(yīng)的大寫(xiě)字符泼掠。(該策略可以在本地作用域中通過(guò)依賴(lài)于語(yǔ)言的 Unicode 聲明來(lái)根據(jù)特定語(yǔ)言的正交規(guī)則替換 titlecase怔软。)不攜帶大小寫(xiě)信息的字符保持它們對(duì)應(yīng)的替換字符串不變。如果模式匹配使用了
:sigspace
修飾符, 那么then a slightly smarter algorithm is used which attempts to determine if there is a uniform capitalization policy over each matched word, and applies the same policy to each replacement word. If there doesn't seem to be a uniform policy on the left, the policy for each word is carried over word by word, with the last pattern word replicated if necessary. If a word does not appear to have a recognizable policy, the replacement word is translated character for character as in the non-sigspace case. Recognized policies include:
lc()
uc()
tc()
tclc()
tcuc()
任何情況下武鲁,只有模式匹配的正式匹配到的字符串部分才被計(jì)數(shù)爽雄,所以任何形式的向前匹配或語(yǔ)境匹配沒(méi)有包含在分析之內(nèi)。
-
:m
(或:ignoremark
) 修飾符的作用域非常像:ignorecase
, 除了它忽略記號(hào)(重音和諸如此類(lèi)) 而非大小寫(xiě)之外沐鼠。它等價(jià)于接收每個(gè)字素(in both target and pattern), 把兩者都轉(zhuǎn)換為 NFD (最大限度地分解)并比較那兩個(gè)根字符(Unicode 無(wú)記號(hào)字符)而忽略任何末尾記號(hào)字符挚瘟。記號(hào)字符只在判斷斷言真假的時(shí)候忽略記號(hào)字符; 實(shí)際匹配的的文本包含了所有的忽略字符, 包含任何跟在最后的根字符后面的東西。
S05-modifier/ignoremark.t lines 14–39
S05-modifier/ignorecase-and-ignoremark.t lines 15–35
:mm
(或:samemark
) 變體能用于替換以把替換字符串更改為和匹配字符串相同的記號(hào)/重音饲梭。這暗示著它和上面的:m
的模式語(yǔ)義相同, 所以, 把:m
和:mm
放在一塊是沒(méi)有必要的乘盖。
S05-modifier/samemark.t lines 9–39通過(guò)字根對(duì)字符執(zhí)行記號(hào)信息。如果右側(cè)字符串比左側(cè)字符串長(zhǎng), 那么剩余的字符在被替換時(shí)不使用任何修改憔涉。 (注意 NFD/NFC 的區(qū)別通常不太重要, 因?yàn)?Perl 把它封裝在了字素模式中订框。) 在
:sigspace
修飾符下, 會(huì)逐字應(yīng)用之前的規(guī)則。:c
(或:continue
) 修飾符讓pattern
從字符串中指定的位置繼續(xù)掃描 (默認(rèn)為$/ ?? $/.to !! 0
):
S05-modifier/continue.t lines 6–50
m:c($p)/ pattern / # 從位置 $p 開(kāi)始掃描, $p 是字符串中的位置,而非模式中的位置
use v6;
#L<S05/Modifiers/"The :c">
my regex simple { . a };
my $string = "1a2a3a";
{
$string ~~ m:c/<&simple>/; # 1a
$string ~~ m:c/<&simple>/; # 2a
$string ~~ m:c/<&simple>/; # 3a
$string ~~ m:c/<&simple>/; # no more 'a's to match
}
{
my $m = $string.match(/.a/); # 1a
$m = $string.match(/.a/, :c(2)); # 2a
$m = $string.match(/.a/, :c(4)); # 3a
}
# this batch not starting on the exact point, and out of order
{
my $m = $string.match(/.a/, :c(0)); # 1a
$m = $string.match(/.a/, :c(3)); # 3a
$m = $string.match(/.a/, :c(1)); # 2a
}
{
my $m = $string.match(/.a/); # 1a
$m = $string.match(/.a/, :continue(2)); # 2a
$m = $string.match(/.a/, :continue(4)); # 3a
}
注意, 這不會(huì)自動(dòng)把 pattern
錨定到開(kāi)始位置. (使用 :p 可以). 提供給 split
的 pattern 默認(rèn)有一個(gè)隱式的 :c
修飾符.
-
:p
(或:pos
) 修飾符讓pattern
只在字符串中指定的位置嘗試匹配:
S05-modifier/pos.t lines 13–111
m:pos($p)/ pattern / # match at position $p
如果參數(shù)被省略兜叨,它就默認(rèn)為 ($/ ?? $/.to !! 0)
. (Unlike in Perl 5, the string itself has no clue where its last match ended.) All subrule matches are implicitly passed their starting position. Likewise, the pattern you supply to a Perl macro's is parsed
trait has an implicit :p
modifier.
注意
m:c($p)/pattern/
正等價(jià)于
m:p($p)/.*? <( pattern )> /
所有的 :g
, :ov
, :nth
, :x
跟 :p
都是不兼容的, 并且會(huì)失敗穿扳, 推薦使用 :c
代替. 允許使用 :ex
修飾符衩侥, 但是只會(huì)在那個(gè)位置產(chǎn)生匹配.
- 新的
:s
(:sigspace
) 修飾符讓空白序列起作用,這些空白被匹配規(guī)則<.ws>
代替. 只有緊跟在匹配結(jié)構(gòu)(原子, 量詞化原子)之后的空白序列是合適的矛物。因此, 出現(xiàn)在任何 regex 開(kāi)頭的空白都會(huì)被忽略, 為了讓能夠參與最長(zhǎng) token 匹配的備選分支更容易書(shū)寫(xiě)茫死。即:
m:s/ next cmd '=' <condition>/
等價(jià)于:
m/ next <.ws> cmd <.ws> '=' <.ws> <condition>/
同樣等價(jià)于:
m/ next \s+ cmd \s* '=' \s* <condition>/
但是在這種情況:
m:s{(a|\*) (b|\+)}
或等價(jià)的:
m { (a|\*) <.ws> (b|\+) }
<.ws>
直到看見(jiàn)數(shù)據(jù)才能決定要做什么. 它仍舊能做對(duì)事情. 不過(guò)不能, 定義你自己的 ws
, 而 :sigspace
會(huì)使用它.`
僅僅當(dāng) rule 可能參與最長(zhǎng) token 匹配時(shí), rule 前面的空白才會(huì)被忽略, 但是在任何顯式備選分支的前面這同樣適用, 因?yàn)橥瑯拥脑颉H绻阆朐谝唤M備選分支前面匹配有意義的空格(sigspace), 把你的空白格放在含有備選分支的括號(hào)外面履羞。
? ?
當(dāng)你這樣寫(xiě):
rule TOP { ^ <stuff> $ }
這等價(jià)于
token TOP { ^ <.ws> <stuff> <.ws> $ <.ws> }
但是注意最后一個(gè) <.ws>
總是匹配空字符串峦萎,因?yàn)? $
錨定字符串的末尾. 如果你的 TOP
rule 沒(méi)有使用 ^
錨定, 它不會(huì)匹配開(kāi)頭的空白.
特別地, 下面的構(gòu)造會(huì)把后面跟著的空白轉(zhuǎn)換為 sigspace
:
任何原子或量詞化的原子
$foo @bar
'a' "$b"
^ $ ^^ $$
(...) [...] <...> 作為整個(gè)原子
(...)* [...]* <...>* 作為量詞化的原子
<( 和 )>
? 和 ? (但是不要那樣使用 ? )
然而這些并不會(huì):
開(kāi)口的 ( 或 [
| 或 ||
& 或 &&
** % 或 %%
:foo 聲明, 包括 :my 和 :sigspace 自身
{...}
當(dāng)我們說(shuō) sigspace 能跟在原子或量詞化的原子后面時(shí), 我們是說(shuō) sigspace 能出現(xiàn)在原子和它的量詞之間:
?
ms/ <atom> * / # 意味著 / [<atom><.ws>]* /
(如果每個(gè)原子匹配空白, 那么就沒(méi)有必要匹配后面的量詞了)忆首。If each atom matches whitespace, then it doesn't need to match after the quantifier.)
一般地, 你不需要在 grammars 中使用 :sigspace
, 因?yàn)榻馕鲆?guī)則會(huì)為你自動(dòng)處理空白策略爱榔。在該上下文中, 空白常會(huì)包含注釋, 根據(jù) grammar 如何去定義它的空白規(guī)則。盡管默認(rèn)的 <.ws>
subrule 識(shí)別不了注釋結(jié)構(gòu), 任何 grammar 能隨意重寫(xiě) <.ws>
規(guī)則糙及。<.ws>
rule 并不意味著在哪兒都是一樣详幽。
給 :sigspace
傳遞一個(gè)參數(shù)也是可能的, 指定一個(gè)完全不同的 subrule 以應(yīng)用。 這可以是任何 rule, 它不需要必須匹配空白丁鹉。當(dāng)談?wù)撨@個(gè)修飾符的時(shí)候, 把模式中的有意義的空白和正被匹配的"空白"區(qū)分開(kāi)很重要, 所以我們會(huì)把模式中的空白叫做 sigspace, 而通常保留 whitespace 來(lái)標(biāo)示當(dāng)前 grammar 中 <.ws>
所匹配到的任何東西妒潭。 sigspace 和 whitespace 之間的一致性是隱喻性的, 這就是為什么一致性既有用又令人迷惑。
除了智能空白匹配, :ss (或 :samespace) 變體還可以用在替換上做智能空白映射揣钦。(即, :ss 暗示了 :s )雳灾。 對(duì)于左側(cè)每個(gè)包含 sigspace 的 <ws>
調(diào)用, 所匹配到的空白被復(fù)制到右側(cè)對(duì)應(yīng)的坑(slot)里, 在想要空白替換的替換字符中由單個(gè)空白符表示。如果右側(cè)比左側(cè)的空白坑多, 則那些右手邊的字符保持自身不變冯凹。如果右側(cè)沒(méi)有足夠的空白坑映射所有從匹配中得到的空白坑, 那么算法會(huì)嘗試通過(guò)從空白列表中隨機(jī)地拼接"普通"空白符來(lái)使信息丟失最小化谎亩。 從最不貴重(valuable)到最貴重, 排列順序?yàn)?
?
spaces
tabs
所有其他水平空白, 包括 Unicode
換行符 (包括作為一個(gè)單元的 crlf)
所有其他垂直空白, 包括 Unicode
這些規(guī)則的主要意圖是發(fā)生在行邊界這樣的替換時(shí)最小化格式分裂。也就是說(shuō), 當(dāng)然, 不保證結(jié)果正是人們想要的宇姚。
?
:s
修飾符很重要, 以至于為它們定義了匹配變體:
S05-modifier/sigspace.t lines 27–48
S05-substitution/subst.t lines 212–222
?
ms/match some words/ # 和 m:sigspace 相同
ss/match some words/replace those words/ # 和 s:samespace 相同
注意 ss///
是就 :ss
而言所定義的, 所以:
$_ = "a b\nc\td";
ss/b c d/x y z/;
結(jié)果就是 a x\ny\tz
.
- 新修飾符可指定 Unicode 級(jí)別:
m:bytes / .**2 / # 匹配兩個(gè)字節(jié)
m:codes / .**2 / # match two codepoints
m:graphs / .**2 / # match two language-independent graphemes
m:chars / .**2 / # match two characters at current max level
- 新的
:Perl5
/:P5
修飾符允許使用 Perl 5 正則語(yǔ)法 (現(xiàn)在不允許你把修飾符放在后面). 例如,
m:P5/(?mi)^(?:[a-z]|\d){1,2}(?=\s)/
等價(jià)于 Perl 6 語(yǔ)法:
m/ :i ^^ [ <[a..z]> || \d ] ** 1..2 <?before \s> /
- 任何一個(gè)整數(shù)修飾符指定一個(gè)計(jì)數(shù). 數(shù)字后面的字符決定了計(jì)數(shù)的種類(lèi):
- 如果后面跟著一個(gè)
x
, 則意味著重復(fù). 一般使用:x(4)
這種形式:
S05-modifier/repetition-exhaustive.t lines 16–30
S05-modifier/repetition.t lines 6–29
s:4x [ (<.ident>) '=' (\N+) $$] = "$0 => $1";
等同于:
s:x(4) [ (<.ident>) '=' (\N+) $$] = "$0 => $1";
這幾乎等同于:
s:c[ (<.ident>) '=' (\N+) $$] = "$0 => $1" for 1..4;
except that the string is unchanged unless all four matches are found. However, ranges are allowed, so you can say :x(1..4)
to change anywhere from one to four matches.
- 如果數(shù)字后面跟著
st
,nd
,rd
, 或th
, 它意味著查找第*N*th
次出現(xiàn). 一般使用:nth(3)
這種形式, 所以
S05-modifier/counted.t lines 13–252
s:3rd/(\d+)/@data[$0]/;
等同于
s:nth(3)/(\d+)/@data[$0]/;
它等價(jià)于
m/(\d+)/ && m:c/(\d+)/ && s:c/(\d+)/@data[$0]/;
?例如:
$_ = "123abc456def789hij"
s:3rd/(\d+)/"PERL"/; # $_ => 123abc456def"PERL"hij
s:2rd/(\d+)/PHP/; # $_ => 123abcPHPdef"PERL"hij
$_ = "0abc1DEF2cfg3OOP";
my @data =('-', '_', ':');
s:3rd/(\d+)/@data[$0]/; # $_ => 0abc1DEF:cfg3OOP
:nth
的參數(shù)允許是一個(gè)整數(shù)列表, 但是這樣的列表應(yīng)該是單調(diào)遞增的.(任何小于等于前一個(gè)值的值都會(huì)被忽略.) 所以:
?
:nth(2,4,6...*) # return only even matches
:nth(1,1,*+*...*) # match only at 1,2,3,5,8,13...
例子:
$_ = "1 2 3 4 5 6 7 8 9";
my @a = m:nth(2,4,6,8)/(\d+)/; # 返回 2 4 6 8
該選項(xiàng)不再要求支持智能匹配匈庭。你可以 grep 一個(gè)整數(shù)列表如果你真的需要那個(gè)能力:
:nth(grep *.oracle, 1..*)
如果 :nth
和 :x
都出現(xiàn)了, 那么相匹配的子例程查找使用 :nth
匹配的子匹配。如果第后 nth 個(gè)匹配的數(shù)量與 :x
中的約束相容, 那么整個(gè)匹配成功, 并且子匹配的可能的數(shù)量最高浑劳。如果 :nth
不是單個(gè)標(biāo)量, 則 :nth
和 :x
通常才有意義阱持。
- 使用新的
:ov
(:overlap
) 修飾符, 當(dāng)前的 regex 會(huì)在所有可能的字符位置上(包括重疊)匹配, 并在列表上下文中返回所有的匹配, 或在 item 上下文中返回間斷的匹配。任一位子的第一個(gè)匹配會(huì)被返回魔熏。匹配保證了相對(duì)于開(kāi)始位置, 會(huì)以從左到右的順序返回衷咽。
S05-modifier/overlapping.t lines 16–67
$str = "abracadabra";
if $str ~~ m:overlap/ a (.*) a / {
@substrings = slice @(); # bracadabr cadabr dabr br
}
- 使用新的
:ex
(:exhaustive
) 修飾符, 當(dāng)前正則會(huì)匹配所有可能的路徑(包括重疊)并返回所有matches
的一個(gè)列表.
S05-modifier/exhaustive.t lines 10–147
S05-modifier/repetition-exhaustive.t lines 17–30
匹配確保會(huì)相對(duì)于起始位置以從左到右的順序返回。每個(gè)起始位置之內(nèi)的順序不能收到保證, 并且可能依賴(lài)于模式和匹配引擎兩者蒜绽。(推測(cè): 或者我們能強(qiáng)制回溯引擎語(yǔ)義镶骗。或者我們可以保證一點(diǎn)也沒(méi)有順序, 除非模式以 ::
開(kāi)始或者某種這樣的東西抑制了 DFAish 方法躲雅。)
?
$str = "abracadabra";
if $str ~~ m:exhaustive/ a (.*?) a / {
say "@()"; # br brac bracad bracadabr c cad cadabr d dabr br
}
注意一旦發(fā)現(xiàn)第一個(gè)匹配, 上面的 ~~
就返回, 而匹配的剩余部分可能通過(guò) @()
來(lái)懶惰地執(zhí)行鼎姊。
?
- 新的
:rw
修飾符讓該 regex 要求當(dāng)前的字符串可以修改而非假設(shè)寫(xiě)時(shí)復(fù)制語(yǔ)義。$/
中所有的捕獲變成了左值字符串, 這樣如果你修改, 例如,$1
, 那么原來(lái)的字符串在那個(gè)位置被修改, 并且所有其它字段的的位置也相應(yīng)地修改(不管它是什么意思)。如果沒(méi)有該修飾符, (特別是如果它尚未實(shí)現(xiàn)或永遠(yuǎn)不會(huì)被實(shí)現(xiàn)), 那么$/
的所有片段都被當(dāng)作是寫(xiě)時(shí)復(fù)制的, 如果不是只讀的話(huà)相寇。
[猜測(cè): 這應(yīng)該真正把模式和字符串變量聯(lián)合在一起, 而不是一個(gè)字符串值(可能是不可變的)]
- 新的
:r
或:ratchet
修飾符讓這個(gè) regex 默認(rèn)不回溯慰于。 (通常你不直接使用這個(gè)修飾符, 因?yàn)樵?token
和rule
聲明符中已經(jīng)隱式地包含了這個(gè)修飾符, 也就是說(shuō) token 和 rule 默認(rèn)也是不回溯的。) 這個(gè)修飾符的作用是在每個(gè)原子(atom)后面暗指一個(gè):
, 包括但不限于*
,+
, 和?
量詞, 還有備選分支唤衫。量詞化原子上的顯式回溯修飾符, 例如**
, 會(huì)重寫(xiě)這個(gè)修飾符东囚。
S05-modifier/ratchet.t lines 5–27
S05-mass/rx.t lines 92–99
-
:i
,:m
,:r
,:s
,:dba
,:Perl5
, 和 Unicode 級(jí)別的修飾符能被放在 regex 里面 (并且是詞法作用域的):
S05-modifier/ignorecase.t lines 18–23
m/:s alignment '=' [:i left|right|cent[er|re]] /
就像外面的修飾符一樣, 只有圓括號(hào)能夠作為副詞的參數(shù)被識(shí)別為合法的括號(hào). 特別地:
m/:foo[xxx]/ Parses as :foo [xxx]
m/:foo{xxx}/ Parses as :foo {xxx}
m/:foo<xxx>/ Parses as :foo <xxx>
- 用戶(hù)自定義修飾符成為可能:
m:fuzzy/pattern/;
- 用戶(hù)自定義修飾符也能接收參數(shù), 但是只能在圓括號(hào)中:
m:fuzzy('bare')/pattern/;
- 要使用括號(hào)作為你的分隔符你必須隔開(kāi):
m:fuzzy (pattern);
或者把 pattern 放在最后:
m:fuzzy(fuzzyargs); pattern ;
- 任何 grammar regex 實(shí)際上是一種
方法
, 并且你可以在這樣一個(gè)子例程中使用一個(gè)冒號(hào)跟著任何作用域聲明符來(lái)聲明一個(gè)變量, 這些聲明符包括my
,our
,state
和constant
(作為類(lèi)似的聲明符, temp 和 let 也能被識(shí)別). 單個(gè)語(yǔ)句(直到結(jié)尾的分號(hào)或行末尾的閉括號(hào)為止) 被解析為普通的 Perl 6 代碼:
token prove-nondeterministic-parsing {
:my $threshold = rand;
'maybe' \s+ <it($threshold)>
}
這種作用域聲明符不會(huì)終止最長(zhǎng) token 匹配, 所以無(wú)效的聲明符可以作為作為一個(gè)掛鉤來(lái)掛起副作用而不改變隨后的模式匹配:
rule breaker {
:state $ = say "got here at least once";
...
}