Groovy Regex:字符串分割模式不返回与匹配器模式相同的结果

l5tcr1uw  于 2023-10-15  发布在  其他
关注(0)|答案(1)|浏览(121)

我正在尝试提取字符串中开始和结束标记之间的数据。有多个匹配,我需要提取所有的匹配(到一个数组或列表中并不重要)
我有一个限制,不能在我的设置中使用Regex 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:MORE 2 C:THAT 3,A:STUFF4 B:MORE 5 C:THAT 6,A:STUFF7 B:MORE 8 C:THAT 9]
但是,当我尝试在string.split上使用相同的模式时,

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

它返回每个匹配的结束和开始标记本身,而不是它们之间的标记。
[无用的东西开始:M,结束:M开始:M,结束:M开始:M,结束:M无用的东西]
我遗漏了什么,为什么Split模式不返回与Matcher模式相同的组?

ipakzgxi

ipakzgxi1#

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

  • 匹配what text
  • 分割by what separator

在这种情况下,Groovy所做的实质上是在标准JavaAPI上添加一些语法糖。线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 ")就可以了。标准的String方法,如indexOflastIndexOfsubstring,可以非常有效地去除无用的东西,只获得所需的组,只需删除第一个START:M之前和最后一个END:M之后的所有内容:

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 ")

(8是START:M的长度)

相关问题