遇到了Java中正则表达式匹配的奇怪行为。第一个输出命令按预期打印true
,但是当同一个字符串打包到Scanner
时,输出为false
。我做错了什么?
public static void main(String[] args) {
Pattern p = Pattern.compile(" *\\[");
System.out.println(p.asPredicate().test("[]")); //true
Scanner s = new Scanner("[]");
System.out.println(s.hasNext(" *\\[")); //false
}
答案 0 :(得分:6)
来自public boolean hasNext(String pattern)
documentation:
如果下一个标记与从指定字符串构造的模式匹配,则返回true。
此处下一个标记为[]
,而不仅仅是[
(因为分隔符是一个或多个空格),但" *\\["
模式不匹配该标记 >(]
不匹配)因此您会按结果false
通知您。
如果您想检查令牌是否以[
开头,您可以在模式的末尾添加.*
以使其与其余令牌匹配。您也可以删除*
,因为空格是默认分隔符,因此它不能成为令牌的一部分。
如果是
Pattern p = Pattern.compile(" *\\[");
System.out.println(p.asPredicate().test("a[]")); //true
如果您查看asPredicate
的代码,您会看到它的实现方式为:
public Predicate<String> asPredicate() {
return s -> matcher(s).find();
}
find()
方法不检查整个字符串是否与模式匹配,但是尝试查找与模式匹配的部分字符串。由于[]
包含零个或多个空格,后跟[
,因此您会看到true
。
答案 1 :(得分:0)
根据Javadoc的Predicate.test
描述:
。如果输入参数与谓词匹配,则返回true,否则返回false
在Javadoc中没有明确写出但是隐含的是test(T t)
方法与String.matches(String)
方法不匹配,其中开始和结束锚是隐式的。另一方面,test
方法与完整字符串不匹配,您需要在正则表达式中使用锚点,使其行为类似于String.matches
或Scanner.hasNext(Pattern )
方法。
以下代码将为这两个调用提供一致的false
结果
final String input = "[]";
final String re = "^ *\\[$"; // note use of anchors in the regex
final Pattern p = Pattern.compile(re);
System.out.println(p.asPredicate().test(input)); // false
Scanner s = new Scanner(input);
System.out.println(s.hasNext(p)); //false
s.close();