【发布时间】:2016-11-08 13:29:47
【问题描述】:
我需要像这样捕获 所有 字符串的元素
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 上很容易看到这种行为。我已经尝试了我所知道的所有“可选”组合。我确定我一定是在做一些愚蠢的事情,而且我已经浪费了足够多的时间来解决这个问题,所以我终于寻求帮助了。
谢谢!
【问题讨论】:
-
Java 和 Javascript 是不同的语言,而且很可能有稍微不同的正则表达式方言。你真正对哪个感兴趣?
-
当您的第三个捕获组第一次测试时,它会针对空字符串进行测试,因为您使用了非贪婪运算符(它会尝试最小的匹配,并在每次匹配时逐渐增加尝试匹配的长度回溯)。这使得第四个捕获组也可以匹配空字符串(可选匹配),然后第五个捕获组捕获字符串的其余部分。无论
grp4="..."是否出现在字符串中,情况总是如此。 -
@JonSkeet 我同意 java 和 javascript 是不同的,但是,在这种情况下,我认为表达式是相同的(Java 中的额外转义除外)。如果解决方案不同,我确实需要用两种语言来做这件事。为了简单起见,我在测试用例中使用了 javascript 语法。
-
@danno57:您假设 Java 和 Javascript 中的正则表达式是相同的。我的经验是,正则表达式的各种方言之间存在细微的差异——除此之外,你的问题并没有说明它们……
标签: javascript java regex