正则表达式与多行模式(Java)中的空字符串不匹配

我刚观察到这种行为;

Pattern p1 = Pattern.compile("^$"); Matcher m1 = p1.matcher(""); System.out.println(m1.matches()); /* true */ Pattern p2 = Pattern.compile("^$", Pattern.MULTILINE); Matcher m2 = p2.matcher(""); System.out.println(m2.matches()); /* false */ 

令我感到奇怪的是,最后一句话是错误的。 这就是文档所说的;

默认情况下,正则表达式^和$忽略行终止符,并且仅分别匹配整个输入序列的开头和结尾。 如果激活MULTILINE模式,则^在输入开始时和任何行终止符之后匹配,但输入结束时除外。 当处于MULTILINE模式时,$匹配行终止符或输入序列的结尾。 HTTP://docs.oracle.com/javase/1.4.2 …

从我得到的,它应该匹配? 以下使事情变得更加混乱;

 Pattern p3 = Pattern.compile("^test$"); Matcher m3 = p3.matcher("test"); System.out.println(m3.matches()); /* true */ Pattern p4 = Pattern.compile("^test$", Pattern.MULTILINE); Matcher m4 = p4.matcher("test"); System.out.println(m4.matches()); /* true */ 

那这是什么? 我怎么理解这个? 我希望有人可以对此有所了解,真的很感激。

如果激活MULTILINE模式,则^在输入开始时和任何行终止符之后匹配,但输入结束时除外。

由于您在输入结束时, ^在多行模式下无法匹配。

这令人惊讶,甚至令人作呕,但仍然根据其文件。

让我们看看你的第二个例子:

 Pattern p2 = Pattern.compile("^$", Pattern.MULTILINE); Matcher m2 = p2.matcher(""); System.out.println(m2.matches()); /* false */ 

所以你有一个m2的行,它是空的或只包含endline的字符而没有其他字符。 因此,为了对应于给定的行,您的模式应该只是“$”,即:

 // Your example Pattern p2 = Pattern.compile("^$", Pattern.MULTILINE); Matcher m2 = p2.matcher(""); System.out.println(m2.matches()); /* false */ // Let's check if it is start of the line p2 = Pattern.compile("^", Pattern.MULTILINE); m2 = p2.matcher(""); System.out.println(m2.matches()); /* false */ // Let's check if it is end of the line p2 = Pattern.compile("$", Pattern.MULTILINE); m2 = p2.matcher(""); System.out.println(m2.matches()); /* true */ 

听起来像个臭虫。 最多,在多行模式中,“^”和“$”可以被解释为在内部线边界处匹配。 Java可能没有像Perl那样的扩展变量状态结构。 我不知道这是不是一个原因。

/^test$/m匹配的事实只是certificate^ $在多行模式下工作,除非字符串为空(在Java中),但显然空字符串的多行模式测试是荒谬的,因为/^$/ work for那。

在Perl中进行测试,一切都按预期工作:

 if ( "" =~ /^$/m ) { print "/^\$/m matches\n"; } if ( "" =~ /^$/ ) { print "/^\$/ matches\n"; } if ( "" =~ /\A\Z/m ) { print "/\\A\\Z/m matches\n"; } if ( "" =~ /\A\Z/ ) { print "/\\A\\Z/ matches\n"; } if ( "" =~ /\A\z/ ) { print "/\\A\\z/ matches\n"; } if ( "" =~ /^/m ) { print "/^/m matches\n"; } if ( "" =~ /$/m ) { print "/\$/m matches\n"; } __END__ /^$/m matches /^$/ matches /\A\Z/m matches /\A\Z/ matches /\A\z/ matches /^/m matches /$/m matches