与Java Matcher匹配的正则表达式无法按预期找到

时间:2015-01-15 20:18:13

标签: java regex matcher

以下是the regex我遇到问题:^(?:(\S+?)(?:\s+|\s*$))。 我正在尝试匹配以下String中此模式的3次出现: -execution thisIsTest1 thisIsTest2。以下是抓取第一个numberOfArgs元素并返回填充了匹配项的List<String>的方法。问题是:返回的List的大小是1 ....循环总是迭代一次然后退出...

private final String arguments="-execution  thisIsTest1  thisIsTest2";
 /**
 * Split the first N arguments separated with one or more whitespaces.
 * @return the array of size numberOfArgs containing the matched elements.
 */
...
public List<String> fragmentFirstN(int numberOfArgs){
    Pattern patt = Pattern.compile("^(?:(\\S+?)(?:\\s+|\\s*$))",Pattern.MULTILINE);
    Matcher matc = patt.matcher(arguments);
    ArrayList<String> args = new ArrayList<>();
    logg.info(arguments);
    int i = 0;
    while(matc.find()&&i<numberOfArgs){
        args.add(matc.group(1));
        i++;
    }
    return args;
}

以下是测试类:

private String[] argArr={"-execution",
        "thisIsTest1",
        "thisIsTest2"
};
...
@Test
public void testFragmentFirstN() throws Exception {
    List<String> arr = test.fragmentFirstN(3);
    assertNotNull(arr);
    System.out.println(arr); ----> prints : [-execution]
    System.out.println(test.getArguments()); ----> prints : -execution  thisIsTest1  thisIsTest2 <-----
    assertEquals(argArr[0],arr.get(0));
--->assertEquals(argArr[1],arr.get(1));<---- IndexOutOfBoundException : Index: 1, Size: 1
    assertEquals(argArr[2],arr.get(2));
    assertEquals(3,arr.size());
}

我认为Matcher#find()在循环时会匹配所有可能的char序列。我错过了什么?

1 个答案:

答案 0 :(得分:2)

问题是正则表达式有一个边界匹配器,它匹配输入字符串的 start ^字符)。在循环中第一次调用Matcher.find()时,匹配的子字符串为-execution。这是因为-execution从字符串的开头开始,正则表达式具有部分(?:\\s+|\\s*$),这意味着检测空格字符(在-execution之后是这种情况)或非空格字符在输入字符串的结尾。

第二次迭代将不匹配任何字符串,因为匹配器不再位于输入字符串的开头。因此Matcher.find()返回false。

您可以尝试删除该字符:

Pattern patt = Pattern.compile("(?:(\\S+?)(?:\\s+|\\s*$))",
            Pattern.MULTILINE);

修改

基于@ ajb的注释,只需删除^字符就可以使正则表达式匹配一个以空格开头的输入字符串。如果不需要,您可以将^替换为\G,用匹配器标记上一场比赛的结束:

Pattern patt = Pattern.compile("\\G(?:(\\S+?)(?:\\s+|\\s*$))",
            Pattern.MULTILINE);