我用过的每一种正则表达式都有“。”字符匹配除了新行(\ r或\ n)之外的所有内容...当然,除非您启用单行标记。
所以,当我尝试以下C#代码时,我感到震惊:
Regex rgx = new Regex(".");
if (rgx.Match("\r\n").Success)
MessageBox.Show("There is something rotten in the state of Redmond!");
它显示了这条消息。为了确保我不会疯狂,我尝试了以下JavaScript代码:
if (/./.test("\r\n"))
alert("Something's wrong with JavaScript too.");
JavaScript没有显示消息,这意味着它的工作正常。
显然,“。” .NET中的字符与“\ r”字符匹配。我检查了documentation以查看是否提及了它:
通配符:匹配任何单个字符 除了\ n。
哇...因为什么样的正则表达式永远让点匹配回车?您会认为.NET的行为与其他所有正则表达式一样......特别是因为它在Windows环境中使用“\ r \ n”作为行分隔符。
我是否可以启用任何标记/设置以使其像其他正则表达式一样工作?是否有任何替代解决方案不涉及用.
替换所有[^\r\n]
个字符?
答案 0 :(得分:16)
在编写Regex Hero时遇到了同样的问题。这有点奇怪。我在博客上发表了关于here的问题。这导致我向测试人员添加了一个功能来启用/禁用CRLF。无论如何,出于某种原因,Microsoft选择使用\ n(换行符)来标记行结尾。
(更新)原因必须与此相关:
Microsoft .NET Framework常规 表达式包含最多 其他常规的流行功能 表达式实现,如 那些在Perl和awk。 旨在成为 兼容Perl 5常规 表达式,.NET Framework常规 表达式包括尚未提供的功能 在其他实现中看到,例如 从右到左的匹配和即时 汇编。 http://msdn.microsoft.com/en-us/library/hs600312.aspx
正如伊戈尔所说,Perl也有同样的行为。
现在,单线和多线RegexOptions会根据点和换行符更改行为。您可以启用Singleline RegexOption,以使点与换行匹配。并且您可以启用Multiline RegexOption,以便^和$标记每一行的开头和结尾(用换行符表示)。但是你不能改变点(。)运算符的固有行为来匹配除\ r \ n。
之外的所有内容答案 1 :(得分:3)
我认为这里的要点是点应该匹配任何不是行分隔符的东西,而\r
是行分隔符。 Perl只能识别\n
,因为它(正如其他人指出的那样)植根于Unix世界,因为它是大多数其他语言中正则表达式的灵感来源。
(但我注意到在Perl 6正则表达式(或规则,使用它们的正式名称)中,/\n/
匹配Unicode识别为行分隔符的任何内容,包括\r\n
序列的两个字符。)
.NET诞生于Unicode时代;它应该识别所有 Unicode认可的行分隔符,包括\r
(较旧的Mac风格)和\r\n
(某些网络协议以及Windows使用)。在Java中考虑这个例子:
String s = "fee\nfie\r\nfoe\rfum";
Pattern p = Pattern.compile("(?m)^.+$");
Matcher m = p.matcher(s);
while (m.find())
{
System.out.println(m.group().length());
}
结果:
3
3
3
3
.
,^
和$
都可以正常使用所有三个行分隔符。现在在C#中尝试:
string s = "fee\nfie\r\nfoe\rfum";
Regex r = new Regex(@"(?m)^.+$");
foreach (Match m in r.Matches(s))
{
Console.WriteLine(m.Value.Length);
}
结果:
3
4
7
这对其他人来说是否合适?这里我们有微软.NET框架内置的正则表达式风格,它甚至没有正确处理Windows标准行分隔符。它完全忽略了单独的\r
,就像其他Unicode行分隔符一样。 .NET在Java之后几年出现,它的Unicode支持至少同样好,所以为什么他们选择坚持这一点呢?
答案 2 :(得分:2)
除单线模式外,.
将匹配除\n
以外的所有字符
正如您所注意到的,它与\r
匹配。
我不知道为什么。
答案 3 :(得分:1)
正则表达式在Unix环境中具有实用(而非理论)的起源,其中LF是行终止符,然后它似乎完全适合。匹配除LF以外的所有东西。
这是一个单一的字符匹配,因此匹配CRLF太多而无法提问和匹配CR或LF可能会导致迁移正则表达式的跨平台问题。我认为使用\ s是一种更好的白空间匹配方法,并且会匹配CR和LF。
答案 4 :(得分:1)
好吧,我不认为“在雷德蒙德州有一些腐烂的东西!”,至少你的情景并不能证明这一点。但我认为这种行为不是一个错误,而是一个功能。为什么?仅仅因为Perl正则表达式具有相同的行为(我只是检查了它),我相信PHP的PCRE(Perl兼容正则表达式)的行为也是一样的。 MS只是使他们的Regex方法的行为与事实上的经典Perl方法相同。现在我的问题是:“JS王国出了什么问题?” :)