我想捕获X {}和Y {}括号之间的文本:
echo "example ,X{whateverX},...,Y{whateverY} the end" | \
perl -ne 'print "$2 $4 \n" if /.*(,X\{(.*?)\}).*(,Y\{(.*?)\})/;'
whateverX whateverY
现在,我想将X和/或Y的存在设置为可选,但是一旦添加可选修饰符,它就会停止匹配/捕获:
echo "example ,X{whateverX},...,Y{whateverY} the end" | \
perl -ne 'print "$2 $4 \n" if /.*(,X\{(.*?)\})?.*(,Y\{(.*?)\})?/;'
<nothing printed>
注意:我在上方添加了?每个X / Y组的和处的修饰符,如下所示(最后一个字符):
.\*(,X\\{(.\*?)\\})**?**
.\*(,Y\\{(.\*?)\\})**?**
例如,这里我只有Y作为可选项,只有X被匹配:
echo "example ,X{whateverX},...,Y{whateverY} the end" | \
perl -ne 'print "$2 $4 \n" if /.*(,X\{(.*?)\}).*(,Y\{(.*?)\})?/;'
whateverX
我希望这三个都产生“ whateverX whatY”,但只有第一个会产生...
我想念什么?为什么将capture-group设置为可选会破坏我的匹配?
答案 0 :(得分:1)
您应该使自己想起正则表达式的基本方面:默认情况下,只要整个表达式都可以匹配,它们就是贪婪的。
您的示例
/.*(,X\{(.*?)\})?.*(,Y\{(.*?)\})?/
仅具有可选元素,因此它将始终匹配-如果没有其他内容,则为空字符串。
问题是,RE将在尽可能早的位置并且在最大可能的范围内保持贪婪(同时仍然能够匹配表达式的其余部分)。因此,第一个.*
将消耗您字符串中的所有内容,而其他子表达式则默认为匹配空字符串(通过?
或*
)。
很难使X {}和Y {}成为可选项,同时仍然希望它们出现。如果将它们设置为可选,则如果可以,则正则表达式引擎最终将永远不会使用它们。
我建议使用在(?:...|...)
内部(随后根据所使用的分支为变量分配值)或在分支重置{{1}中存在的X {}和Y {}交替组合的子表达式}(为使用(?|...|...)
而编写为正确的代码):
/x
将输出:
use strict;
use warnings;
foreach my $data (<DATA>) {
chomp $data;
if ($data =~ /
(?|
.*? # both X and Y present
,X \{ ([^{}]*) \}
.*?
,Y \{ ([^{}]*) \}
|
.*? # only X present
,X \{ ([^{}]*) \}
.*
()
|
.*? # only Y present
()
,Y \{ ([^{}]*) \}
|
() () # neither X nor Y present
)
/x) {
print "$1, $2\n";
}
}
exit 0;
__DATA__
example ,X{whateverX},...,Y{whateverY} the end
example2 ,X{whateverX2},random data to the end
example3 with data before ,Y{whateverY3} the end
example4 with just data and no separators
请注意,前导whateverX, whateverY
whateverX2,
, whateverY3
,
是必需的,否则.*?
最终将在每种情况下都匹配。
答案 1 :(得分:0)
特别是因为您的第二个组是可选的,因此您需要确保中间的舍弃匹配第二个块的开头与中间的。*不匹配:
echo "example ,X{whateverX},...,Y{whateverY} the end" | \
perl -ne 'print "$2 $4 \n" if /.*(,X\{(.*?)\})(?:(?!,Y).)*(,Y\{(.*?)\})?/;'
whateverX whateverY
其中重要的一点是:
(?:(?!,Y).)*
(?:)确保这不是捕获组
(?!,Y)确保此块不包含字符串,Y
如果要更精确,也可以使用(?!,Y {)。
答案 2 :(得分:0)
另一种可以说简单得多的方法:让引擎使用global修饰符每行完成多个匹配。这样,您的模式就变成了琐碎的交替,而没有所有.*
或?
的恶作剧:
/X\{(?<X>.*?)\}|Y\{(?<Y>.*?)\}/g