Java重复模式匹配(2)

时间:2011-10-08 17:22:17

标签: java regex matching repeat

考虑以下正则表达式:

(([^\|])*\|)*([^\|]*)

这匹配

类型的重复字符串模式
("whatever except |" |) {0 to any times} ("whatever except |" |) {1 time}

所以它应该匹配下面的字符串,它有17个子字符串(16个重复,加上" z"作为最后一个)。

"abcd  | e | fg | hijk | lmnop | |   | qrs |   t| uv| w |||||x   y|  z"

确实,RegexPal验证给定的正则表达式是否与上述字符串匹配。

现在,我想获得每个子串(即" abcd |"," e |"," fg |"等。),对于它们的数量,长度等没有先验知识。

根据标题相似的previous StackOverflow postMatcherfind()方法的文档,我只需要执行类似

的操作
Pattern pattern = Pattern.compile(regex); // regex is the above regex
Matcher matcher = pattern.matcher(input); // input is the above string

while (matcher.find())
{
   System.out.println(matcher.group(1));
}

然而,当我这样做时,我只打印出2个字符串:最后重复的子字符串(" x y |")和空值;绝对不是我期望的16个子串。

在运行find()循环之前,检查匹配是否确实发生也是一件好事,但我不确定matches(),{{1在groupCount() > 0也匹配的情况下,应该使用一些其他条件而不进行两次匹配工作。

所以,问题

  1. 如何获得所有16个重复的子串?
  2. 如何获取最后一个子字符串?
  3. 如何检查字符串是否匹配?

2 个答案:

答案 0 :(得分:4)

我担心你会让事情变得混乱。无论何时使用重复('*','+'等),都无法获得所有匹配的实例。使用类似((xxx)*)的内容,您可以将整个字符串匹配为group(1),将最后一部分匹配为group(2),而不是其他内容。

考虑使用String.split或更好的番石榴Splitter


广告1.你不能。使用像

这样的简单模式
\G([^\|])*(\||$)

find()一起按顺序获取所有匹配项。请注意\G锚定到上一场比赛。


广告2.如何获取最后一个子字符串?

最后一个结果find返回。


广告3.如何检查字符串是否匹配?

在您上一次find检查matcher.end() == input.length之后。但是使用这种模式,你不需要检查任何东西,因为它总是匹配。

答案 1 :(得分:1)

如果必须使用正则表达式...

  

1)如何获得所有16个重复的子串?

见下文。骑自行车进行比赛时,您不需要匹配所有内容,只需要您想要的部分。 (我得到17场比赛 - 这是正确的吗?)

  

2)如何获取最后一个子字符串?

将delim切换到正则表达式的开头,并允许'^'。

  

3)如何检查字符串是否匹配?

什么是不匹配的资格?任何字符串都匹配。


以下是使用正则表达式的解决方案:

String input = "abcd  | e | fg | hijk | lmnop | |   | qrs |   t| uv| w |||||x   y|  z";
int expectedSize = 17;
List<String> expected = new ArrayList<String>(Arrays.asList("abcd  ", " e ", " fg ", " hijk ", " lmnop ", " ", "   ", " qrs ", "   t", " uv", " w ", "",
    "", "", "", "x   y", "  z"));

List<String> matches = new ArrayList<String>();

// Pattern pattern = Pattern.compile("(?:\\||^)([^\\|]*)");
Pattern pattern = Pattern.compile("(?:_?\\||^)([^\\|]*?)(?=_?\\||$)"); // Edit: allows _| or | as delim

for (Matcher matcher = pattern.matcher(input); matcher.find();)
{
  matches.add(matcher.group(1));
}

for (int idx = 0, len = matches.size(); idx < len; idx++)
{
  System.out.format("[%-2d] \"%s\"%n", idx + 1, matches.get(idx));
}

assertSame(expectedSize, matches.size());
assertEquals(expected, matches);

输出

[1 ] "abcd  "
[2 ] " e "
[3 ] " fg "
[4 ] " hijk "
[5 ] " lmnop "
[6 ] " "
[7 ] "   "
[8 ] " qrs "
[9 ] "   t"
[10] " uv"
[11] " w "
[12] ""
[13] ""
[14] ""
[15] ""
[16] "x   y"
[17] "  z"