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
(\.[^:/]+)
匹配 http://www.google.com
.*$
匹配 /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
如果没有 MULTILINE
或 DOTALL
模式,您的正则表达式:(\.[^:/]+).*$
将无法匹配输入,因为存在 .*$
因为点将不匹配换行符和 $
(行尾)出现在 2 个换行符之后。
我知道 $
用于检查 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
(\.[^:/]+)
匹配http://www.google.com
.*$
匹配/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
如果没有 MULTILINE
或 DOTALL
模式,您的正则表达式:(\.[^:/]+).*$
将无法匹配输入,因为存在 .*$
因为点将不匹配换行符和 $
(行尾)出现在 2 个换行符之后。