与 Java Matcher 匹配的正则表达式不会按预期找到
Regex matching with Java Matcher won't find as expected
这是 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;
}
这是测试 class :
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()
在循环时会匹配所有可能的字符序列。我错过了什么?
问题是正则表达式有一个边界匹配器匹配输入字符串的 start(^
字符)。循环中第一次调用Matcher.find()
,匹配到的子串是-execution
。这是因为 -execution
从字符串的开头开始,并且正则表达式具有 (?:\s+|\s*$)
部分,这意味着检测 space 个字符(-execution
之后的情况)或非-space 输入字符串末尾的字符。
第二次迭代不会匹配任何字符串,因为匹配器不再位于输入字符串的开头。因此 Matcher.find()
returns false.
您可以尝试删除字符:
Pattern patt = Pattern.compile("(?:(\S+?)(?:\s+|\s*$))",
Pattern.MULTILINE);
编辑:
根据@ajb 的评论,简单地删除 ^
字符将使正则表达式匹配以白色 space 开头的输入字符串。如果不需要,您可以将 ^
替换为 \G
,这标志着匹配器上一场比赛的结束:
Pattern patt = Pattern.compile("\G(?:(\S+?)(?:\s+|\s*$))",
Pattern.MULTILINE);
这是 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;
}
这是测试 class :
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()
在循环时会匹配所有可能的字符序列。我错过了什么?
问题是正则表达式有一个边界匹配器匹配输入字符串的 start(^
字符)。循环中第一次调用Matcher.find()
,匹配到的子串是-execution
。这是因为 -execution
从字符串的开头开始,并且正则表达式具有 (?:\s+|\s*$)
部分,这意味着检测 space 个字符(-execution
之后的情况)或非-space 输入字符串末尾的字符。
第二次迭代不会匹配任何字符串,因为匹配器不再位于输入字符串的开头。因此 Matcher.find()
returns false.
您可以尝试删除字符:
Pattern patt = Pattern.compile("(?:(\S+?)(?:\s+|\s*$))",
Pattern.MULTILINE);
编辑:
根据@ajb 的评论,简单地删除 ^
字符将使正则表达式匹配以白色 space 开头的输入字符串。如果不需要,您可以将 ^
替换为 \G
,这标志着匹配器上一场比赛的结束:
Pattern patt = Pattern.compile("\G(?:(\S+?)(?:\s+|\s*$))",
Pattern.MULTILINE);