Groovy Regex:字符串拆分模式不会返回与匹配器模式

时间:2018-02-23 22:49:22

标签: regex groovy split matcher

我试图在字符串中的起始和结束标记之间提取数据。有多个匹配,我需要提取所有匹配(进入数组或列表并不重要)

我有一个限制,不能在我的设置中使用正则表达式匹配器,以便我可以选择使用带有正则表达式的string.split()

def str = "USELESS STUFF START:M A:STUFF1 B:MORE2 C:THAT3 END:M START:M A:STUFF4 B:MORE5 C:THAT6 END:M START:M A:STUFF7 B:MORE8 C:THAT9 END:M USELESS STUFF"

此模式适用于Regex Matcher,并提取开始和结束标记之间的所有匹配。

def items = str =~ /(?s)(?<=START:M).*?(?=END:M)/

结果:

  

[A:STUFF1 B:MORE2 C:THAT3,A:STUFF4 B:MORE5 C:THAT6,A:STUFF7 B:MORE8 C:THAT9]

但是,当我尝试在string.split

上使用相同的模式时
def items = str.split(/(?s)(?<=START:M).*?(?=END:M)/)

它会为每个匹配返回结束和开始标记,而不是它们之间的匹配。

  

[USELESS STUFF START:M,END:M START:M,END:M START:M,END:M USELESS STUFF]

我缺少什么,为什么拆分模式不会返回与匹配模式相同的组?

1 个答案:

答案 0 :(得分:1)

此行为与方法名称很好地对应:

  • 匹配what text
  • 拆分by what separator

在这种情况下,Groovy所做的事实上是在标准Java API上添加一些语法糖。第def items = str =~ /(?s)(?<=START:M).*?(?=END:M)/行 与

相同
Matcher items = Pattern.compile("(?s)(?<=START:M).*?(?=END:M)").matcher(str);

此匹配器找到的组将是

 A:STUFF1 B:MORE2 C:THAT3 
 A:STUFF4 B:MORE5 C:THAT6 
 A:STUFF7 B:MORE8 C:THAT9

当Matcher返回匹配时,Splitter相反,它们会被它们分开 - 它通过给定的正则表达式查找文本的部分并将它们视为分隔符,将它们删除并返回剩下的内容:

START:M
//  A:STUFF1 B:MORE2 C:THAT3 is cut out since it's a separator
END:M START:M
//  A:STUFF4 B:MORE5 C:THAT6 is a separator
END:M START:M
//  A:STUFF7 B:MORE8 C:THAT9 is a separator
END:M

要实际获取STARTEND标记之间的数据,str.split(" END:M START:M | START:M | END:M ")会这样做。像indexOflastIndexOfsubstring这样的标准字符串方法可以非常有效地摆脱无用的东西,只需在第一个{{1之前删除所有内容在最后START:M之后:

END:M

(8是str.substring(str.indexOf("START:M ") + 8, str.lastIndexOf(" END:M")) .split(" END:M START:M ") // or more groovy str[str.indexOf("START:M ") + 8 .. str.lastIndexOf(" END:M") - 1] .split(" END:M START:M ") )的长度