Java:Pattern在Scanner中的行为有所不同

时间:2017-07-05 12:46:53

标签: java regex java.util.scanner

遇到了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
}

2 个答案:

答案 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.matchesScanner.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();