如何从Perl正则表达式字符串中任意嵌套的子组中删除捕获?我想将任何正则表达式嵌套到一个包围表达式中,该表达式将子正则表达式捕获为一个整体以及静态已知的后续组。我是否需要手动将正则表达式字符串转换为使用所有未捕获的(?:)
组(并希望我不要搞乱),或者是否有提供此功能的Perl正则表达式或库机制?
# How do I 'flatten' $regex to protect $2 and $3?
# Searching 'ABCfooDE' for 'foo' OK, but '((B|(C))fo(o)?(?:D|d)?)', etc., breaks.
# I.E., how would I turn it effectively into '(?:(?:B|(?:C))fo(?:o)?(?:D|d)?)'?
sub check {
my($line, $regex) = @_;
if ($line =~ /(^.*)($regex)(.*$)/) {
print "<", $1, "><", $2, "><", $3, ">\n";
}
}
附录:我隐约知道$&
,$`
和$'
,并建议尽量避免使用它们,而且我无权访问${^PREMATCH}
,${^MATCH}
和${^POSTMATCH}
在我的Perl 5.8环境中。可以使用上述方法将上面的示例划分为2/3块,更复杂的实际情况可以手动进行迭代,但是我认为,如果可能,我希望有一个通用的解决方案。
[Accepted Answer:
我希望存在,但令人惊讶的是(至少对我而言)没有,这是一个使内容不透明的封装组,因此后续的位置反向引用将内容视为单个实体,而名称引用是范围外的gbacon对于Perl 5.10+具有潜在的有用解决方法,FM显示了针对任何版本的手动迭代机制,可以在特定情况下实现相同的效果,但是j_random_hacker称没有真正的语言机制可以封装子表达式。如何从Perl正则表达式字符串中任意嵌套的子组中删除捕获?我想将任何正则表达式嵌套到一个包围表达式中,该表达式也将子正则表达式捕获为一个整体实体...
一般来说,不能。
保护您关心的子模式的一种方法是使用named capture buffers:
[这不能解决一般情况,但是您可以在标量上下文中使用/g
选项来处理您的特定示例,这将使您将问题分为两个匹配项,第二个从第一个中断的地方开始:] >
sub check {
my($line, $regex) = @_;
my ($left_side, $regex_match) = ($1, $2) if $line =~ /(^.*)($regex)/g;
my $right_side = $1 if $line =~ /(.*$)/g;
print "<$left_side> <$regex_match> <$right_side>\n"; # <AB> <CfooD> <E123>
}
check( 'ABCfooDE123', qr/((B|(C))fo(o)?(?:D|d)?)/ );
Perl v5.22和更高版本具有/n
修饰符,可关闭所有捕获。
这不会禁用捕获,但是可能会完成您想要的操作:
$ perl -wle 'my $_ = "123abc"; /(\d+)/ && print "num: $1"; { /([a-z]+)/ && print "letter: $1"; } print "num: $1";'
num: 123
letter: abc
num: 123