给定的正则表达式代码是
import java.util.regex.*;
public class Test {
public static void main(String[] args) {
String longString = " Derek Banas CA 12345 PA (412)555-1212 johnsmith@hotmail.com 412-555-1234 412 555-1234 ";
regexChecker("\\s[A-Za-z]{2,20}\\s", longString);
}
public static void regexChecker(String theRegex, String str2Check){
Pattern checkRegex = Pattern.compile(theRegex);
Matcher regexMatcher = checkRegex.matcher( str2Check );
while ( regexMatcher.find() ){
if (regexMatcher.group().length() != 0){
System.out.println( regexMatcher.group().trim() );
System.out.println( "Start Index: " + regexMatcher.start());
System.out.println( "Start Index: " + regexMatcher.end());
}
}
}
}
这里的输出是
Derek
Start Index: 0
Start Index: 7
CA
Start Index: 12
Start Index: 16
PA
Start Index: 21
Start Index: 25
1>为什么Derek的输出是'结束指数7'而不是6?
2>为什么'Banas'不是输出的一部分?
任何帮助都将不胜感激。
答案 0 :(得分:0)
您的模式包含非空格后的空格。这就解释了你的问题的两个:“Derek”和“Banas”之间的空间是第一场比赛的一部分,这使得它成为“Banas”比赛的一部分(因为你是在“巴纳斯”之前需要另一个空间来匹配)。
如果您同时将\\s
更改为\\b
,它将匹配字边界 - 不使用该空格。然后输出:
Derek
Start Index: 1
Start Index: 6
Banas
Start Index: 7
Start Index: 12
CA
Start Index: 13
Start Index: 15
PA
Start Index: 22
Start Index: 24
johnsmith
Start Index: 39
Start Index: 48
hotmail
Start Index: 49
Start Index: 56
com
Start Index: 57
Start Index: 60
此时你可能会得到你不想要的比赛。
您可以继续捕获前面的空白,但最后删除一个空格。像这样的模式:
regexChecker("\\s[A-Za-z]{2,20}", longString);
输出:
Derek
Start Index: 0
Start Index: 6
Banas
Start Index: 6
Start Index: 12
CA
Start Index: 12
Start Index: 15
PA
Start Index: 21
Start Index: 24
johnsmith
Start Index: 38
Start Index: 48
答案 1 :(得分:0)
模式匹配一个空格,2到20个ASCII字母和一个空格之后。这意味着第一个匹配的结尾是Derek
之后的空格,即第7个索引。
这也说明了Banas
不匹配的事实:第一场比赛已经消耗了Banas
之前的空间,而第一场\s
与B
不匹配,因此,Banas
被跳过。
您需要使最后\s
非消耗,请使用
"\\s[A-Za-z]{2,20}(?!\\S)"
^^^^^^
请参阅regex demo。
(?!\S)
否定前瞻与字符串中的位置匹配,该位置后面紧跟着空格或字符串结尾。请注意,您也可以使用类似的"技巧"使用第一个\s
,如果您将其转换为(?<!\S)
lookbehind,"(?<!\\S)[A-Za-z]{2,20}(?!\\S)"
。然后,没有空格将落在匹配值内。
请参阅this regex demo。
解决此问题的另一种方法是使用\b
字边界,这也是零宽度断言,"\\b[A-Za-z]{2,20}\\b"
。