有一些因素会导致捕获索引重置,其中之一是使用 |
和 ||
。
将其放置在另一个捕获组中也会导致重置。(因为匹配结果是一棵树。)
在设计Raku时,一切都被重新设计以更加一致、有用和强大,包括正则表达式。
如果你有一个像这样的选择:
/ (foo) | (bar) /
您可能想这样使用它:
$line ~~ / (foo) | (bar) /;
say %h{ ~$0 };
如果
(bar)
是
$1
的话,你需要这样写才行:
$line ~~ / (foo) | (bar) /;
say %h{ ~$0 || ~$1 };
通常情况下,捕获组编号从零开始更有用。
这样做也使正则表达式更像通用编程语言。(每个“块”都是一个独立的子表达式。)
有时重新编号捕获组可能很不错。
/ ^
[ (..) '-' (..) '-' (....) # mm-dd-yyyy
| (..) '-' (....) # mm-yyyy
]
$ /
注意,yyyy
部分是根据 dd
部分是否包含而分别为 $2
或 $1
。
my $day = +$2 ?? $1 !! 1;
my $month = +$0;
my $year = +$2 || +$1;
我们可以将
yyyy
重新编号为始终为
$2
。
/ ^
[ (..) '-' (..) '-' (....) # mm-dd-yyyy
| (..) '-' $2 = (....) # mm-yyyy
]
$ /
my $day = +$1 || 1;
my $month = +$0;
my $year = +$2;
如果我们还需要接受 yyyy-mm-dd
,该怎么办呢?
/ ^
[ (..) '-' (..) '-' (....) # mm-dd-yyyy
| (..) '-' $2 = (....) # mm-yyyy
| $2 = (....) '-' $0 = (..) '-' $1 = (..) # yyyy-mm-dd
]
$ /
my $day = +$1 || 1
my $month = +$0;
my $year = +$2;
实际上,现在我们有很多捕获组,让我们再看一下如果|
不会导致编号的捕获组从$0
重新开始,我们将如何处理它。
/ ^
[ (..) '-' (..) '-' (....) # mm-dd-yyyy
| (..) '-' (....) # mm-yyyy
| (....) '-' (..) '-' (..) # yyyy-mm-dd
]
$ /
my $day = +$1 || +$7 || 1;
my $month = +$0 || +$3 || +$6;
my $year = +$2 || +$4 || +$5;
这不太好。
首先,您需要确保正则表达式和my $day
正确匹配。
快速计算捕获组数量,确保这些数字与正确的捕获组匹配。
当然,仍然存在一个问题,即具有名称的概念实际上被数字捕获。
因此,我们应该使用名称代替。
/ ^
[ $<month> = (..) '-' $<day> = (..) '-' $<year> = (....) # mm-dd-yyyy
| $<month> = (..) '-' $<year> = (....) # mm-yyyy
| $<year> = (....) '-' $<month> = (..) '-' $<day> = (..) # yyyy-mm-dd
]
$ /
my $day = +$<day> || 1;
my $month = +$<month>;
my $year = +$<year>;
简单来说,我会这样做:
/ $<foo> = (foo) | $<bar> = (bar) /;
if $<foo> {
…
} elsif $<bar> {
…
}
|
替代运算符执行最长令牌匹配(LTM),而不是顺序(即“首个命名”)令牌匹配。请参见:https://docs.raku.org/language/regexes#Longest_alternation:_| and https://docs.raku.org/language/5to6-nutshell.html#Longest_token_matching_(LTM)_displaces_alternation。 - jubilatious1