我需要捕获像这样的字符串的所有元素
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
它当然根本不匹配。
那么好吧,我可以像这样将第四组设置为可选,对吗?
([\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
第四组即使存在也不再匹配。
FWIW,我需要所有文本(所有组都必须是捕获组),因为我最终使用它来操作组 2 和 4 的文本(如果存在),并重新构成字符串。就像将示例字符串变成这样
front stuff grp2="123" middle stuff grp4="456" end stuff
在 regex101.com 上很容易看到这种行为。我已经尝试了我所知道的所有“可选”组合。我确信我一定做了一些愚蠢的事情,而且我已经浪费了足够的时间试图弄清楚,所以我终于寻求帮助。
谢谢!
最佳答案
您可以将中间的middle stuff
和grp4
设置为可选,因为两者都有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
关于javascript - 正则表达式可选捕获未按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40488212/