捕获可选的子串

时间:2014-09-23 14:56:11

标签: regex optional capture regex-group

我正在尝试匹配这些行:

X=1 a b c Y=5 a bb aa
X=2 aa ccc d
X=3 ccc Y=9 d ee ff

'Y = x'子串是可选的。它可能存在于一条线上或不存在。 我想在组1中捕获X = x,在可选组2中捕获Y = x。

我正在使用这个正则表达式:

^(X=[0-9]+?).+?(Y=[0-9]+?)?.+?$

整条线都匹配,但我只捕获第一组。即使存在可选的子字符串,也不会捕获第二个组。问题是X =和Y =之间可能有很多不同的单词(也有'='字符)。

有关如何捕获可选组2的任何想法吗?

实际示例:http://regex101.com/r/rD4sO4/1

3 个答案:

答案 0 :(得分:3)

更新

这是一个更有效,更清洁的选择(不需要轮换):

^(X=[0-9]+)(?:.+?(Y=[0-9]+))?.+?$

Demo

请注意,我从[0-9]删除了延迟重复,因为您不应该遇到任何匹配太多字符的问题。


说明

原始表达式不起作用,因为正则表达式从左到右匹配(因为你使用了懒惰的重复,我假设你理解正则表达式的概念是"贪婪")。因此,即使您的中间.+?是懒惰的,Y=[0-9]+也是可选的,因此它可以继续匹配到尾随/必需.+?$。这可能不是人们所期望的,因为有一个懒惰的重复......但是当你总是可以回溯并尝试再次匹配它时,为什么要停止一个可选的段。

我的工作是因为只有.+?存在才能使中间Y=[0-9]+存在。因此总是会检查Y=[0-9]+,但是如果找不到则可以,因为整个组仍然是可选的。然后我们仍然可以尾随.+?$结束。


原始

我为了更简洁的答案而绞尽脑汁,但是我使用了交替来让正则表达式引擎在匹配所有内容之前始终检查Y=[0-9]+?

^(X=[0-9]+)(?:.+?(Y=[0-9]+).+?|.+?)$

Demo

答案 1 :(得分:1)

或此模式

(X=\d+)(?>[^Y\r\n]+|Y(?!=\d+))*(Y=\d+)?  

Demo

答案 2 :(得分:1)

(X=\d+)|(Y=\d+)

试试这个。看看演示。

http://regex101.com/r/lS5tT3/21