Raku 正则表达式:如何知道哪个组在交替时被捕获
Raku regex: How to know which group was captured at an alternation
使用 perl(以及几乎任何正则表达式风格),每个组都按顺序编号。
例如,这段代码:
'bar' =~ m/(foo)|(bar)/;
print // 'x'; # (1-based index)
print // 'x'; # (1-based index)
打印xbar
但是,对于 Raku,它的行为就像有一个 branch reset group 包裹了整个正则表达式:
'bar' ~~ m/(foo)|(bar)/;
print [=11=] // 'x'; # (0-based index)
print // 'x'; # (0-based index)
打印barx
我可以接受这种行为:)。但是,有时了解哪个组在交替下被捕获是很有用的。
如何知道有乐的群?
有几种方法可以做到,实用程度各不相同。
一种方法是明确告诉 Raku 你想要的数字是什么:
'bar' ~~ m/=(foo)|=(bar)/;
如果您扩展正则表达式,计数将继续为 3 美元。
一种 less-recommendable 的方法是偷偷加入一组额外的括号:
'bar' ~~ m/(foo)|()(bar)/;
foo
将匹配 $0 中的第一个,$1 将是未定义的,而 bar
将匹配 $1 且 $0 为空(但不是未定义)。 TIMTOWTDI 但这不是一个好的 ;-)
另一种方法是使用标志:
my $flag;
'bar' ~~ m/(foo {$flag = 'first'} ) | (bar {$flag = 'second'} )/;
标志将根据匹配设置。这实际上可以是一种 not-terrible 做事的方式,特别是如果你的标志是二进制的并且你会有一些逻辑你会 运行 超过它。
另一种类似的方法是利用通常在操作 类 中使用的 .make
/.made
,但仍然可以内联使用:
'bar' ~~ m/(foo {make 'first'} ) | (bar {make 'second'} )/;
say [=13=].made; # 'second'
如果您有很多元数据想要与之相关联,那么这个非常好(但如果只知道选择了哪个,可能有点过头了)。
有几件事会导致捕获索引重置。 |
和 ||
恰好是一个。
将它放在另一个捕获组中是另一回事。 (因为匹配结果是一棵树。)
在设计 Raku 时,所有内容都经过重新设计,使其更一致、更有用且更强大。包括正则表达式。
如果你有这样的交替:
/ (foo) | (bar) /
您可能想这样使用它:
$line ~~ / (foo) | (bar) /;
say %h{ ~[=11=] };
如果 (bar)
改为 </code>,则必须这样写:</p>
<pre><code>$line ~~ / (foo) | (bar) /;
say %h{ ~[=12=] || ~ };
捕获组编号从零重新开始通常更有用。
这也使得正则表达式更像是一种通用编程语言。 (每个“块”都是一个独立的子表达式。)
现在有时重新编号捕获组可能会很好。
/ ^
[ (..) '-' (..) '-' (....) # mm-dd-yyyy
| (..) '-' (....) # mm-yyyy
]
$ /
请注意 yyyy
部分是 </code> 或 <code>
取决于是否包含 dd
部分。
my $day = + ?? !! 1;
my $month = +[=14=];
my $year = + || +;
我们可以将 yyyy
重新编号为始终 </code>。</p>
<pre><code>/ ^
[ (..) '-' (..) '-' (....) # mm-dd-yyyy
| (..) '-' = (....) # mm-yyyy
]
$ /
my $day = + || 1;
my $month = +[=15=];
my $year = +;
或者如果我们还需要接受 yyyy-mm-dd
怎么办
/ ^
[ (..) '-' (..) '-' (....) # mm-dd-yyyy
| (..) '-' = (....) # mm-yyyy
| = (....) '-' [=16=] = (..) '-' = (..) # yyyy-mm-dd
]
$ /
my $day = + || 1
my $month = +[=16=];
my $year = +;
实际上现在我们有很多捕获组,让我们再看看如果 |
没有导致编号的捕获组从 [=32=]
[=34= 重新开始,我们将如何处理它]
/ ^
[ (..) '-' (..) '-' (....) # mm-dd-yyyy
| (..) '-' (....) # mm-yyyy
| (....) '-' (..) '-' (..) # yyyy-mm-dd
]
$ /
my $day = + || + || 1;
my $month = +[=17=] || + || +;
my $year = + || + || +;
不太好。
一方面,您必须确保正则表达式和 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> {
…
}
使用 perl(以及几乎任何正则表达式风格),每个组都按顺序编号。
例如,这段代码:
'bar' =~ m/(foo)|(bar)/;
print // 'x'; # (1-based index)
print // 'x'; # (1-based index)
打印xbar
但是,对于 Raku,它的行为就像有一个 branch reset group 包裹了整个正则表达式:
'bar' ~~ m/(foo)|(bar)/;
print [=11=] // 'x'; # (0-based index)
print // 'x'; # (0-based index)
打印barx
我可以接受这种行为:)。但是,有时了解哪个组在交替下被捕获是很有用的。
如何知道有乐的群?
有几种方法可以做到,实用程度各不相同。
一种方法是明确告诉 Raku 你想要的数字是什么:
'bar' ~~ m/=(foo)|=(bar)/;
如果您扩展正则表达式,计数将继续为 3 美元。
一种 less-recommendable 的方法是偷偷加入一组额外的括号:
'bar' ~~ m/(foo)|()(bar)/;
foo
将匹配 $0 中的第一个,$1 将是未定义的,而 bar
将匹配 $1 且 $0 为空(但不是未定义)。 TIMTOWTDI 但这不是一个好的 ;-)
另一种方法是使用标志:
my $flag;
'bar' ~~ m/(foo {$flag = 'first'} ) | (bar {$flag = 'second'} )/;
标志将根据匹配设置。这实际上可以是一种 not-terrible 做事的方式,特别是如果你的标志是二进制的并且你会有一些逻辑你会 运行 超过它。
另一种类似的方法是利用通常在操作 类 中使用的 .make
/.made
,但仍然可以内联使用:
'bar' ~~ m/(foo {make 'first'} ) | (bar {make 'second'} )/;
say [=13=].made; # 'second'
如果您有很多元数据想要与之相关联,那么这个非常好(但如果只知道选择了哪个,可能有点过头了)。
有几件事会导致捕获索引重置。 |
和 ||
恰好是一个。
将它放在另一个捕获组中是另一回事。 (因为匹配结果是一棵树。)
在设计 Raku 时,所有内容都经过重新设计,使其更一致、更有用且更强大。包括正则表达式。
如果你有这样的交替:
/ (foo) | (bar) /
您可能想这样使用它:
$line ~~ / (foo) | (bar) /;
say %h{ ~[=11=] };
如果 (bar)
改为 </code>,则必须这样写:</p>
<pre><code>$line ~~ / (foo) | (bar) /;
say %h{ ~[=12=] || ~ };
捕获组编号从零重新开始通常更有用。
这也使得正则表达式更像是一种通用编程语言。 (每个“块”都是一个独立的子表达式。)
现在有时重新编号捕获组可能会很好。
/ ^
[ (..) '-' (..) '-' (....) # mm-dd-yyyy
| (..) '-' (....) # mm-yyyy
]
$ /
请注意 yyyy
部分是 </code> 或 <code>
取决于是否包含 dd
部分。
my $day = + ?? !! 1;
my $month = +[=14=];
my $year = + || +;
我们可以将 yyyy
重新编号为始终 </code>。</p>
<pre><code>/ ^
[ (..) '-' (..) '-' (....) # mm-dd-yyyy
| (..) '-' = (....) # mm-yyyy
]
$ /
my $day = + || 1;
my $month = +[=15=];
my $year = +;
或者如果我们还需要接受 yyyy-mm-dd
/ ^
[ (..) '-' (..) '-' (....) # mm-dd-yyyy
| (..) '-' = (....) # mm-yyyy
| = (....) '-' [=16=] = (..) '-' = (..) # yyyy-mm-dd
]
$ /
my $day = + || 1
my $month = +[=16=];
my $year = +;
实际上现在我们有很多捕获组,让我们再看看如果 |
没有导致编号的捕获组从 [=32=]
[=34= 重新开始,我们将如何处理它]
/ ^
[ (..) '-' (..) '-' (....) # mm-dd-yyyy
| (..) '-' (....) # mm-yyyy
| (....) '-' (..) '-' (..) # yyyy-mm-dd
]
$ /
my $day = + || + || 1;
my $month = +[=17=] || + || +;
my $year = + || + || +;
不太好。
一方面,您必须确保正则表达式和 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> {
…
}