为了账号安全,请及时绑定邮箱和手机立即绑定

相对于什么是在 java.util.Scanner 中评估的正则表达式?

相对于什么是在 java.util.Scanner 中评估的正则表达式?

慕容708150 2023-03-09 10:18:04
我注意到以下我无法解释的奇怪行为:import java.util.Scanner;public class Main {  public static void main(String[] args) {    var scanner = new Scanner("ab");    System.out.println(scanner.findInLine("."));  // output: a    System.out.println(scanner.findInLine("."));  // output: b  }}但import java.util.Scanner;public class Main {  public static void main(String[] args) {    var scanner = new Scanner("ab");    System.out.println(scanner.findInLine("."));  // output: a    System.out.println(scanner.findInLine("^.")); // output: null  }}我不明白第二个片段与第一个片段有何不同。根据文档,^匹配一行的开头,但事实并非如此,因为:a在行匹配的开头,a在输入匹配的开头,以及b在扫描仪匹配的位置。如果正则表达式不是相对于扫描仪的位置进行评估的,那么它相对于什么进行评估?
查看完整描述

2 回答

?
守候你守候我

TA贡献1802条经验 获得超10个赞

关于这两个代码片段,扫描器只是通过了a而不是整行。要转到下一行,您需要调用scanner.nextLine().

类的 findInLine(Pattern pattern) 方法java.util.Scanner尝试查找指定模式的下一次出现,忽略定界符。如果在下一个行分隔符之前找到模式,则 扫描器前进到匹配的输入并返回与模式匹配的字符串。如果在直到下一个行分隔符的输入中没有检测到这样的模式,则返回 null 并且扫描仪的位置不变。

https://www.geeksforgeeks.org/scanner-findinline-method-in-java-with-examples/

例子:

    Scanner scanner = new Scanner("abcde\nx");
    System.out.println(scanner.findInLine("."));    // output: a
    System.out.println(scanner.findInLine("."));    // output: b

这里扫描器匹配了第一个字符 (a) 并移动到仍在同一行的 b。

    Scanner scanner = new Scanner("abcde\nx");
    System.out.println(scanner.findInLine("."));     // output: a
    scanner.nextLine();
    System.out.println(scanner.findInLine("."));     // output: x

在这里,扫描仪的工作方式与以前相同,但我已经移过了第一行分隔符。


查看完整回答
反对 回复 2023-03-09
?
Smart猫小萌

TA贡献1911条经验 获得超7个赞

一切都在那里,只是记录不完整。以下是findInLine实现方式:


public String findInLine(Pattern pattern) {

    // omitted: validate parameters

    // omitted: ensure the internal buffer is large enough


    return findWithinHorizon(pattern, horizonForLine);

}

来源:java/util/Scanner.java


以下是文档必须说明的内容findWithinHorizon:


[...] 扫描仪将地平线视为透明的、非锚定的边界 [...]。


来源:java.util.Scanner#findWithinHorizon(java.util.regex.Pattern,int)


关于锚定边界:


[...] 如果没有锚定边界,这个匹配器区域的边界将不会匹配诸如^和 之类的锚点$。[...]


来源:java.util.regex.Matcher##useAnchoringBounds(boolean)


以下是findWithinHorizon实现方式:


public String findWithinHorizon(Pattern pattern, int horizon) {

    // omitted: validate parameters


    while (true) {

        if (findPatternInBuffer(pattern, horizon)) {

            matchValid = true;

            return matcher.group();

        }


        // omitted: check if more input is required

    }

    return null;

}

来源:java/util/Scanner.java


以下是findPatternInBuffer实现方式:


private boolean findPatternInBuffer(Pattern pattern, int horizon) {

    // omitted: calculating search limit


    matcher.region(position, searchLimit);


    // omitted: matching pattern

}

java/util/Scanner.java


这就是为什么第二个模式不匹配的原因。正则表达式只在光标前搜索,不认为^适用于光标所在位置。但是它适用于输入的开头,因此第一个模式匹配。


这并不意味着每个带有的正则表达式^都会失败,后面的正面观察会起作用:


import java.util.Scanner;


public class Main {

  public static void main(String[] args) {

    var scanner = new Scanner("ab");


    System.out.println(scanner.findInLine("."));        // output: a

    System.out.println(scanner.findInLine("(?<=^.).")); // output: b

  }

}


查看完整回答
反对 回复 2023-03-09
  • 2 回答
  • 0 关注
  • 104 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信