为什么.NET正则表达式不将\ n视为行尾字符?
示例代码:
string[] words = new string[] { "ab1", "ab2\n", "ab3\n\n", "ab4\r", "ab5\r\n", "ab6\n\r" };
Regex regex = new Regex("^[a-z0-9]+$");
foreach (var word in words)
{
Console.WriteLine("{0} - {1}", word, regex.IsMatch(word));
}
这是我得到的回应:
ab1 - True
ab2
- True
ab3
- False
- False
ab5
- False
ab6
- False
为什么正则表达式匹配ab2\n
?
更新 我不认为Multiline是一个很好的解决方案,也就是说,我想验证登录以仅匹配指定的字符,并且它必须是单行。如果我更改MultiLine选项的构造函数ab1,ab2,ab3和ab6匹配表达式,则ab4和ab5不匹配。
答案 0 :(得分:10)
.NET正则表达式引擎确实将\n
视为行尾。如果您的字符串具有Windows样式的\r\n
换行符,则会出现问题。 RegexOptions.Multiline启用了$
和\r
之间的\n
匹配,而不是\r
之前的匹配。
$
也匹配字符串的最后一部分,就像\z
一样。不同之处在于\z
只能在字符串的最后匹配,而$
也会在尾随\n
之前匹配。使用RegexOptions.Multiline时,$
也会在任何\n
之前匹配。
如果您在使用换行符时遇到问题,首先需要进行搜索和替换,以便将所有\r
替换为空,以确保所有行仅以\n
结尾。
答案 1 :(得分:9)
如果字符串以换行符结束,RegexOptions.Multiline
将无效。 $
将忽略最后一个换行符,因为之后没有任何内容。
如果要匹配到字符串的最后并忽略任何换行符,请使用\z
Regex regex = new Regex(@"^[a-z0-9]+\z", RegexOptions.Multiline);
这适用于MutliLine和SingleLine,这无关紧要。
答案 2 :(得分:1)
来自RegexOptions
:
多线模式。更改^和$的含义,使它们分别在任何行的开头和结尾匹配,而不仅仅是整个字符串的开头和结尾。
所以基本上如果您将RegexOptions.Multiline
传递给Regex
构造函数,那么您指示该实例将最终的 $
视为换行符的匹配项 - 不仅仅是字符串本身的结尾。
答案 3 :(得分:1)
使用正则表达式选项,System.Text.RegularExpressions.RegexOptions:
string[] words = new string[] { "ab1", "ab2\n", "ab3\n\n", "ab4\r", "ab5\r\n", "ab6\n\r" };
Regex regex = new Regex("^[a-z0-9]+$");
foreach (var word in words)
{
Console.WriteLine("{0} - {1}", word,
regex.IsMatch(word,"^[a-z0-9]+$",
System.Text.RegularExpressions.RegexOptions.Singleline |
System.Text.RegularExpressions.RegexOptions.IgnoreCase |
System.Text.RegularExpressions.RegexOptions.IgnorePatternWhitespace));
}
答案 4 :(得分:0)
可能是因为windows / linux行结束差异。但是\n\n
以这种方式得到错误仍然很奇怪......你试过设置RegexOptions.Multiline
标志吗?
答案 5 :(得分:0)
只是为了给Smazy答案提供更多细节。这是一个摘录自: Jan Goyvaerts和Steven Levithan撰写的正则表达手册。版权所有2009 Jan Goyvaerts和Steven Levithan,978-0-596-2068-7
<\ Z>和<\ z>之间的区别 最后一次发挥作用 主题文字中的字符是 越线。在那种情况下,<\ Z>可以 在主题的最后匹配 文本,在最后一行换行后,为 就在那条线之前 打破。好处是你可以 无需搜索
担心剥离尾随 在你的主题结束时换行 文本。读取文件时 线,一些工具包括线 在行尾打破,而 别人不这样做; <\ Z>掩盖了这个 区别。 <\ z>仅匹配 主题文本的结尾,所以它 如果是尾随行,则不匹配文本 打破了。锚<$>是 相当于<\ Z>,只要你这样做 不要打开“^和$匹配” 打破“选择。此选项已关闭 所有正则表达式的默认值除外 红宝石。 Ruby没有提供的方法 关闭此选项。就像<\ Z>一样, <$>匹配在最后 主题文本,以及之前 最后的换行符,如果有的话。
当然,如果没有Smazy的答案,我就不会发现它。