我试图在字符串中的起始和结束标记之间提取数据。有多个匹配,我需要提取所有匹配(进入数组或列表并不重要)
我有一个限制,不能在我的设置中使用正则表达式匹配器,以便我可以选择使用带有正则表达式的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]
我缺少什么,为什么拆分模式不会返回与匹配模式相同的组?
答案 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
要实际获取START
和END
标记之间的数据,str.split(" END:M START:M | START:M | END:M ")
会这样做。像indexOf
,lastIndexOf
和substring
这样的标准字符串方法可以非常有效地摆脱无用的东西,只需在第一个{{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 ")
)的长度