正则表达式可选捕获无法按预期工作

时间:2016-11-08 13:29:48

标签: javascript java regex

我需要像这样

捕获字符串的所有元素
front stuff grp2="abc" middle stuff grp4="xyz" end stuff

这样就分成了这五组

#1: front stuff
#2: grp2="abc"
#3: middle stuff
#4: grp4="xyz"
#5: end stuff

只要所有五个部分都存在

,这个表达就可以解决问题
([\s\S]*?)(grp2=\"\S*?\")([\s\S]*?)(grp4=\"\S*?\")([\s\S]*)

但是如果grp4 =“...”不存在,例如,

front stuff grp2="abc" end stuff

它当然根本不匹配。

好吧,我可以让第4组像这样选择,对吗?

([\s\S]*?)(grp2=\"\S*?\")([\s\S]*?)(grp4=\"\S*?\")?([\s\S]*)

显然是错的。产生的是这个(当存在grp4时)

#1: front stuff
#2: grp2="abc"
#3: 
#4: 
#5: middle stuff grp4="xyz" end stuff

第4组即使存在也不再匹配。

FWIW,我需要所有文本(所有组必须捕获组),因为我最终使用它来操作组2和组4的文本(如果它们存在),并重构字符串。就像拿这个例子字符串并把它变成这个

一样
front stuff grp2="123" middle stuff grp4="456" end stuff

在regex101.com上很容易看到这种行为。我已经尝试了我所知道的“可选”的每一种组合。我敢肯定我一定是在做一些愚蠢的事情,而且我已经浪费了足够的时间来弄明白,所以我终于要求帮助了。

谢谢!

2 个答案:

答案 0 :(得分:1)

您可以在中间选择middle stuffgrp4,因为两者都有end stuff。您的新正则表达式为([\\s\\S]*?)(grp2=\"\\S*?\")(?:([\\s\\S]*?)(grp4=\"\\S*?\")){0,1}([\\s\\S]*)

String test = "front stuff grp2=\"abc\" middle stuff grp4=\"xyz\" end stuff";
Pattern p = Pattern.compile("([\\s\\S]*?)(grp2=\"\\S*?\")(?:([\\s\\S]*?)(grp4=\"\\S*?\")){0,1}([\\s\\S]*)");
Matcher m = p.matcher(test);

for(int i=1; i<=m.groupCount(); i++) {
    if(m.group(i)!=null) {
        System.out.println(i+": "+m.group(i));
    }
}
// String test = "front stuff grp2=\"abc\" middle stuff grp4=\"xyz\" end stuff";
// 1: front stuff 
// 2: grp2="abc"
// 3:  middle stuff 
// 4: grp4="xyz"
// 5:  end stuff

// String test = "front stuff grp2=\"abc\" end stuff";
// 1: front stuff 
// 2: grp2="abc"
// 3:  end stuff

答案 1 :(得分:0)

正则表达式中的 | 使您能够在蒙版上设置OR选项。

你可以使用这种公式: ([\ S \ S] ?)(GRP2 = \&#34; \ S \&#34;?)(?[\ S \ S] )(GRP4 = \& #34; \ S \&#34;?)([\ S \ S] )的 | ([\ S \ S] )(GRP2 ?= \&#34; \ S * \&#34)([\ S \ S] )的 | ([\ S \ S] )(GRP4 = \&#34; \ S * \&#34)([\ S \ S *)

即使grp2不存在或grp4不存在或两者都存在,这里也能正常工作。

希望得到这个帮助。