我对以下正则表达式有疑问。 我有一个想要匹配的字符串
String test = "Server returned HTTP response code: 403 for URL: https://an.url.example";
我想使用此正则表达式从该字符串中“提取”错误代码:
Pattern pattern = Pattern.compile(".*\\s([\\d]{3})\\s.*");
Matcher matcher = pattern.matcher(test);
System.out.println(matcher.group(1));
但是当我运行这段代码时,我总是遇到这个异常:
java.lang.IllegalStateException: No match found
at java.base/java.util.regex.Matcher.checkMatch(Matcher.java:1852)
at java.base/java.util.regex.Matcher.group(Matcher.java:687)...
然后我认为我的正则表达式是错误的,我在网站上测试了它。
现在我更困惑了,我真的不知道我做错了什么(也许是方法调用?)。 我只是希望有人能帮助我并消除我的困惑。 祝你有美好的一天!
你的正则表达式本身看起来不错。您遇到的问题的出现是因为您在尝试使用
find()
检索组值之前尚未执行匹配操作 group(1)
。 Matcher.find()
方法尝试查找输入序列中与模式匹配的下一个子序列,必须先调用该方法,然后才能使用 group()
检索匹配组
匹配器的API是这样工作的:
您创建了匹配器,然后您需要调用一个方法来实际运行它。这个想法是你可以写这样的东西:
while (matcher.find()) {
int number = Integer.parseInt(matcher.group(1));
System.out.println("Found a number: " + number);
}
就您而言,您只关心单个发现。因此,您可能想要
if
,而不是 while
,这里:
Matcher matcher = pattern.matcher(test);
if (matcher.find()) {
System.out.println(matcher.group(1));
} else {
// What do you want to do if 'test' does not contain this string?
}
请注意,您的正则表达式过于复杂。您所需要的只是
Pattern.compile(" (\\d{3}) ")
- \\s
是如果您想捕获其他空白(例如制表符),但这显然不在您的输入中,并且无需将 []
放在 \\d
周围。从技术上讲,只需 \\d{3}
就可以做到这一点,但是,这会在长度超过 3 位的数字中找到多个匹配项。更简洁的做法可能只是 "\\b\\d{3}\\b"
,将整个事物视为匹配(因此,.group(0)
) - \\b
表示“断词”,根本不捕获任何字符,它只是在“空格”中匹配Between' - 字符串开头、字符串结尾、空格、制表符,这类东西标志着“断字”。
find()
只找到第一个匹配项。还有 matches()
,它类似于 find() ,只不过它检查整个输入是否匹配。有了你的 .*
界限,它会的,但是 find()
并且将 .*
排除在外要简单得多。