正则表达式与多行模式下的空字符串不匹配 (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中有一行,它是空的或者只包含结束线的字符,不包含其他字符。因此,为了对应给定的行,您的模式应该只有"$",即:

// 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 */

听起来像个bug。在多行模式下,"^"one_answers"$"最多可以被解释为在内部行边界匹配。Java可能没有像Perl那样扩展可变状态结构。我不知道这是否是一个原因。

事实上,/^test$/m匹配只是证明^$在多行模式下工作,除非字符串为空(在Java中),但很明显,空字符串的多行模式测试是荒谬的,因为/^$/适用于此。

在Perl中测试,一切如预期:

if ( "" =~ /^$/m   ) { print "/^$/m    matchesn"; }
if ( "" =~ /^$/    ) { print "/^$/     matchesn"; }
if ( "" =~ /AZ/m ) { print "/\A\Z/m  matchesn"; }
if ( "" =~ /AZ/  ) { print "/\A\Z/   matchesn"; }
if ( "" =~ /Az/  ) { print "/\A\z/   matchesn"; }
if ( "" =~ /^/m    ) { print "/^/m     matchesn"; }
if ( "" =~ /$/m    ) { print "/$/m     matchesn"; }

__END__

/^$/m    matches
/^$/     matches
/AZ/m  matches
/AZ/   matches
/Az/   matches
/^/m     matches
/$/m     matches

最新更新