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

时间:2019-07-04 18:58:05

标签: java regex java.util.scanner

我注意到以下无法解释的怪异行为:

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
  }
}

我不明白第二个片段与第一个片段有何不同。

根据the documentation^匹配行的开头,但事实并非如此,因为:

    该行开头的
  1. a
  2. 输入匹配开头的
  3. a
  4. 扫描仪位置上的
  5. b匹配。

如果未对正则表达式进行相对于扫描仪位置的求值,那么相对于正则表达式求值的是什么?

2 个答案:

答案 0 :(得分:0)

关于两个代码段,扫描程序仅经过a,而不是整行。要转到下一行,您需要致电scanner.nextLine()

  

java.util.Scanner类的findInLine(图案模式)方法   尝试忽略指定模式的下一个出现   定界符。如果在下一个行分隔符之前找到该模式,   扫描仪将前进经过匹配的输入并返回   匹配模式的字符串。如果在   输入直到下一个行分隔符,然后返回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

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

答案 1 :(得分:0)

就在那里,只是文献记载不多。 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
  }
}