我正在用Java手工开发一个语法分析器,我想使用正则表达式来解析各种标记类型。问题是,如果输入不符合语法,我也希望能够准确地报告当前的行号。
长话短说,当我尝试将换行符与Scanner类实际匹配时,我遇到了一个问题。具体地说,当我尝试使用Scanner类将换行符与模式进行匹配时,它失败了。几乎总是如此。但是,当我使用Matcher和相同的源字符串执行相同的匹配时,它检索到的换行符也完全符合您的预期。有没有这样的原因,我似乎没有发现,或者这是一个bug,正如我怀疑的那样?
仅供参考:我在Sun数据库中找不到描述此问题的bug,因此如果是bug,则尚未报告。
示例代码:
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发布于 2010-05-20 09:28:47
您的useDelimiter()和next()组合有问题。useDelimiter("")将在next()上返回一个长度为1的子字符串,因为实际上每两个字符之间就有一个空字符串。
也就是说,因为"\r\n".equals("\r" + "" + "\n")所以"\r\n"实际上是两个标记,"\r"和"\n",由""分隔。
要获取Matcher-behavior,您需要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 newlinesAPI链接
findWithinHorizon(Pattern pattern, int horizon)尝试查找指定模式的下一个匹配项...忽略分隔符...如果没有检测到这样的模式,则返回null ...如果horizon为0,则...此方法继续搜索输入,查找未绑定的指定模式。相关问题
useDelimiter("")将标记为1个长度的substrings
发布于 2010-05-20 09:11:40
事实上,这是两者的预期行为。扫描器主要关心使用分隔符将事物拆分成令牌。因此,它(懒惰地)获取您的sourceString,并将其视为以下一组标记:\r、\n、\n、\r、\r、\n和\n。然后,当您调用hasNext时,它会检查下一个令牌是否与您的模式匹配(多亏了\r\n?上的?,它们都很容易做到这一点)。因此,while循环会遍历这7个标记中的每一个。
另一方面,匹配器将贪婪地匹配正则表达式-因此,它会将\r\n捆绑在一起。
强调扫描器行为的一种方法是将您的正则表达式更改为(\\r\\n|\\n)。这将导致计数为0。这是因为扫描程序将第一个令牌读取为\r (而不是\r\n),然后注意到它与您的模式不匹配,因此当您调用hasNext时返回false。
(简而言之:在使用令牌模式之前,扫描器使用分隔符进行标记,匹配器不做任何形式的标记)
发布于 2010-05-20 09:09:51
值得一提的是,您的示例是模棱两可的。可能是:
\r
\n
\n
\r
\r
\n
\n(七行)
或者:
\r\n
\n
\r
\r\n
\n(五行)
那个?您使用的量词是一个贪婪的量词,这可能会使five成为正确的答案,但因为Scanner迭代标记(在您的例子中是单个字符,由于您选择的定界模式),它将不情愿地匹配,一次一个字符,得出不正确的答案7。
https://stackoverflow.com/questions/2870393
复制相似问题