Java 正则表达式中的新行和美元符号

New line and dollar sign in Java regular expression

我知道 $ 用于检查 Java 正则表达式中是否有行尾。

对于以下代码:

String test_domain = "http://www.google.com/path\nline2\nline3";
test_domain = test_domain.replaceFirst("(\.[^:/]+).*$?", "");
System.out.println(test_domain);

输出为:

http://www.google.com
line2
line3

我假设模式 (\.[^:/]+).*$? 匹配第一行,即 http://www.google.com/path</code> 是 <code>http://www.google.com? 勉强匹配(因此匹配第一行。)

但是,如果我删除模式中的 ? 并执行以下代码:

String test_domain = "http://www.google.com/path\nline2\nline3";
test_domain = test_domain.replaceFirst("(\.[^:/]+).*$", "");
System.out.println(test_domain);

输出为:

http://www.google.com/path
line2
line3

我觉得应该可以给出结果http://www.google.com

  1. (\.[^:/]+) 匹配 http://www.google.com
  2. .*$ 匹配 /path\nline2\nline3

我对正则表达式的误解在哪里?

您的正则表达式与输入字符串不匹配。事实上,$ 匹配字符串的结尾(在 line3 的结尾)。由于您没有使用 s 标志,因此 . 无法到达那里。

注意! $ 锚 - 即使没有 Pattern.MULTILINE 选项 - 可以匹配最后一个换行符之前的位置,参见 What is the difference between ^ and \A , $ and \Z in regex?. This can be easily tested with "a\nb\n".replaceAll("$", "X"), resulting in "a\nbX\nX", see this Java demo.

此外,line/string 锚点的 $ 末尾不能有 ? 量词。它对正则表达式引擎没有意义,在 Java.

中被忽略

要让它正常工作,你需要使用 s 标志,如果你只想 return http://www.google.com:

String test_domain = "http://www.google.com/path\nline2\nline3";
test_domain = test_domain.replaceFirst("(?s)(\.[^:/]+).*$", "");
System.out.println(test_domain);

this demo 的输出:

http://www.google.com

使用多行 (?m) 标志,正则表达式将处理每一行以查找文字 .,然后是 :/ 以外的字符序列。当找到其中一个字符时,该行的其余字符将被忽略。

    String test_domain = "http://www.google.com/path\nline2\nline3";
    test_domain = test_domain.replaceFirst("(?m)(\.[^:/]+).*$", "");
    System.out.println(test_domain);

this IDEONE demo 的输出:

http://www.google.com
line2
line3

您有一个多行输入并尝试在您的正则表达式中为每一行使用锚 $ 但不使用 MULTILINE 标志。您所需要的只是正则表达式前面的 (?m) 模式:

String test_domain = "http://www.google.com/path\nline2\nline3";
test_domain = test_domain.replaceFirst("(?m)(\.[^:/]+).*$", "");
System.out.println(test_domain);

这将输出:

http://www.google.com
line2
line3

RegEx Demo

如果没有 MULTILINEDOTALL 模式,您的正则表达式:(\.[^:/]+).*$ 将无法匹配输入,因为存在 .*$ 因为点将不匹配换行符和 $(行尾)出现在 2 个换行符之后。