使用正则表达式解析Java Scanner换行符(Bug?)

SEK*_*SEK 4 java regex newline java.util.scanner

我正在用Java手工开发语法分析器,我想使用正则表达式解析各种令牌类型.问题是,如果输入不符合语法,我还希望能够准确报告当前行号.

简而言之,当我尝试将换行符与Scanner类匹配时,我遇到了一个问题.具体来说,当我尝试使用Scanner类将换行符与模式匹配时,它会失败.几乎总是.但是当我使用匹配器和相同的源字符串执行相同的匹配时,它会完全按照您的预期检索换行符.这是否有原因,我似乎无法发现,或者这是一个错误,我怀疑?

仅供参考:我无法在Sun数据库中找到描述此问题的错误,因此如果是错误,则尚未报告.

示例代码:

Pattern newLinePattern = Pattern.compile("(\\r\\n?|\\n)", Pattern.MULTILINE);
String sourceString = "\r\n\n\r\r\n\n";
Scanner scan = new Scanner(sourceString);
scan.useDelimiter("");
int count = 0;
while (scan.hasNext(newLinePattern)) {
    scan.next(newLinePattern);
    count++;
}
System.out.println("found "+count+" newlines"); // finds 7 newlines
Matcher match = newLinePattern.matcher(sourceString);
count = 0;
while (match.find()) {
    count++;
}
System.out.println("found "+count+" newlines"); // finds 5 newlines
Run Code Online (Sandbox Code Playgroud)

pol*_*nts 6

useDelimiter()next()组合是错误的.useDelimiter("")将返回1长度子字符串next(),因为空字符串实际上位于每两个字符之间.

也就是说,因为"\r\n".equals("\r" + "" + "\n")这样"\r\n"其实两个标记,"\r"并且"\n",通过分隔"".

要获得Matcher行为,你需要findWithinHorizon忽略分隔符.

    Pattern newLinePattern = Pattern.compile("(\\r\\n?|\\n)", Pattern.MULTILINE);
    String sourceString = "\r\n\n\r\r\n\n";
    Scanner scan = new Scanner(sourceString);
    int count = 0;
    while (scan.findWithinHorizon(newLinePattern, 0) != null) {
        count++;
    }
    System.out.println("found "+count+" newlines"); // finds 5 newlines
Run Code Online (Sandbox Code Playgroud)

API链接

  • findWithinHorizon(Pattern pattern, int horizon)

    试图找到指定模式的下一次出现[...]忽略分隔符[...]如果没有检测到这样的模式,null则返回[...]如果horizon为0,则[...]此方法继续搜索输入,无需绑定即可查找指定的模式.

相关问题