捕获组仅返回每个组的最后一次出现

时间:2011-05-02 18:25:39

标签: java regex regex-group

我有这样的字符串:

String s = "word=PS1,p1,p2,p3=q1,q2|word2=PS3,p4,p5,p6=q3";

或者像这样:

String s2 = "word3=PS2,p7,p8=q4,q5,q6|=PS3,p9=";

或者像这样:

String s3 = "=PS3=";

所以,在形式中 - 字符串包含字典中的一些单词定义,由“|”分割符号

这里:

  • 单词 - 字典中的单词(可选,如S2或S3)

  • PS1,PS2,PS3 - 词性标签(必填)

  • p1,p2,... - 一些参数(可选)

  • q1,q2,q3,... - 其他一些参数(也是可选的)

我想构建正则表达式,它会在文本中找到所有这些字符串,并为我提供组:

  • group1 - word
  • group2 - 词性标记
  • group3,group4,... - 参数p
  • 组(k),组(k + 1),...... - 另一个参数(q)

我不关心最后一个p参数和第一个q参数的组索引。我应该知道,第一组 - 是单词(可能为空),第二组 - 词性,以及其他组 - 参数p和q。

现在我有这样的正则表达式:

"([a-z]*)?=([A-Z]+)(,?[a-z]+)*=(,?[a-z]+)*")

但它无法正常工作。它只显示最后一个参数p和q。即(对于S2):

  • group1 = word3 - 确定
  • group2 = PS2 - 确定
  • group3 = p8 - 不行(仅限最后一个p参数)
  • group4 = q6 - 不行(也是最后的q参数)

你能帮帮我吗?

更新的:    “=” - 仅表示p参数和q参数之间的分割字符。在我的问题中没有必要。您应该认为,p参数和q参数没有区别。

真实输入的例子:

String s = "bread=NOUN,plur,link=form|=VERB="

2 个答案:

答案 0 :(得分:2)

Regex中不能有可变数量的捕获组。在.Net中,每个组可以有多个捕获,但不能用Java。问题在于,正则表达式引擎只存储每个组的最后一次成功匹配。你能做的最好的事情是将所有的p-和q-参数匹配成两个大的组,然后将它们分开。

Pattern pattern1 = Pattern.compile(
    "([^|=,]*)" +                // Group 1: The word. Zero or more characters.
    "=([^|=,]*)" +               // Group 2: The part of speech.
    ",?([^|=,]*(?:,[^|=,]*)*)" + // Group 3: The p-params
    "=([^|=,]*(?:,[^|=,]*)*)"    // Group 4: The q-params
);
Matcher matcher = pattern1.matcher("word=PS1,p1,p2,p3=q1,q2|word2=PS3,p4,p5,p6=q3");
while (matcher.find()) {
  String word = matcher.group(1);
  String partOfSpeech = matcher.group(2);
  String pParamString = matcher.group(3);
  String qParamString = matcher.group(4);
  String[] pParams = pParamString.split(",");
  String[] qParams = qParamString.split(",");
  // Do something with the above variables...
}

我使用[^|=,]*来匹配任何非特殊字符。

答案 1 :(得分:1)

当我遇到这样的问题时,我会关注量词的修饰符。您可能希望将某些量词修改为贪婪,例如

(?,[A-Z] +)+ *

上面的这个差异是,最终零或更多量词现在尽可能多地获得。这只是一个例子,我不能确定那个特定的修饰符是你需要的,但是,鉴于你的表达式就像你报告的那样工作,看起来这些修饰符很可能会让它完全得到它。

相关问题