.NET的Regex类和换行符

时间:2009-06-12 20:43:56

标签: c# .net regex

为什么.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不匹配。

6 个答案:

答案 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的答案,我就不会发现它。