Java:模式在扫描仪中的行为不同

Posted

技术标签:

【中文标题】Java:模式在扫描仪中的行为不同【英文标题】:Java: Pattern behaves differently in Scanner 【发布时间】:2017-12-09 03:37:04 【问题描述】:

在 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

【问题讨论】:

试试s.hasNext(p) @horcrux 来自 javadoc:此方法的调用形式为 hasNext(pattern) * 行为方式与调用完全相同 * hasNext (Pattern.compile(pattern)). @SpaceTrucker 你是对的。所以重点是Pattern.compile(myRegex)p.asPredicate().test(myString)myString中搜索myRegex的出现,而new Scanner(myString).hasNext(myRegex)检查myString的全部内容是否与myRegex匹配。 【参考方案1】:

来自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

【讨论】:

我明白了。是否有可能检查令牌的开始,或者我应该在每个正则表达式的末尾添加.* 这里最简单的方法是在末尾添加.*。但是根据您真正想要实现的目标,最好避免使用 Scanner 并直接使用 Pattern ?不知道你真正想要达到的目标是很难说的。 我正在解析字符串,其中包含一个类似 JSON 的数组,所以我需要直接访问字符和解析整个 int 或 float 的简单方法。在这种情况下是否有任何替代扫描仪的方法。不能使用 JSON 解析器,这种情况不能通用处理。 @ViacheslavKroilov 如果没有看到真实数据和预期结果,我不能说太多。由于这个问题已经很少有关于当前描述的问题的答案,所以修改它是不好的,因为它会使发布的答案无效。因此,如果您想询问您的具体情况,请考虑创建单独的问题。【参考方案2】:

根据来自 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();      

【讨论】:

以上是关于Java:模式在扫描仪中的行为不同的主要内容,如果未能解决你的问题,请参考以下文章

使用 \R 模式使用 Java 扫描仪(缓冲区边界问题)

鸿蒙之WiFi联网

扫描仪扫描文件处理-Photoshop批处理弹出色阶设置框解决

如何配置休眠以扫描不同模块中的实体

探索AI视觉技术新应用,夸克扫描王首推“离线模式”端侧AI算法提升隐私安全

使用 Java 扫描器读取文件