.NET正则表达式点字符与回车符匹配?

.NET正则表达式点字符与回车符匹配?,.net,regex,.net,Regex,我使用过的每一种正则表达式都有“.”字符匹配,但不匹配新行(\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 (/./

我使用过的每一种正则表达式都有“.”字符匹配,但不匹配新行(\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”字符匹配。我查了一下报纸,看看有没有提到:

通配符:匹配任何单个字符 除了\n

哇。。。从什么时候起,正则表达式风格的点与回车符匹配?你可能会认为.NET的行为会像所有其他的正则表达式一样。。。特别是因为它位于使用“\r\n”作为行分隔符的Windows环境中


是否有任何标志/设置可以让它像在其他正则表达式中一样工作?是否有任何替代解决方案不涉及将所有
字符替换为
[^\r\n]

正则表达式在Unix环境中有一个实际(而不是理论)来源,其中LF是行终止符,因此它似乎完全适合于。匹配除LF之外的所有内容


这是一个单字符匹配,所以匹配CRLF的要求太高,匹配CR或LF可能会导致跨平台迁移regex的问题。我认为使用\s将是一种更好的空白匹配方法,并且将同时匹配CR和LF。

我在编写Regex-Hero时遇到了同样的问题。这有点奇怪。我在博客上写了这个问题。这导致我在测试仪中添加了一个功能来启用/禁用CRLFs。无论如何,出于某种原因,Microsoft选择使用\n(换行符)来标记换行符

(更新)原因必须与此相关:

Microsoft.NET Framework常规 表达式包含了最多 其他常规功能的流行特性 表达式实现,例如 Perl和awk中的那些设计为 与Perl5兼容 表达式,.NET Framework正则表达式 表达式包含尚未包含的功能 可以在其他实现中看到,例如 从右到左匹配和动态 汇编

正如Igor所指出的,Perl具有相同的行为


现在,单线和多线改变了基于点和换行的行为。您可以启用单线RegexOption,以便点匹配换行符。您可以启用多行RegexOption,以便^和$标记每行的开始和结束(由换行符表示)。但是您不能更改点(.)运算符的固有行为以匹配除单线模式之外的所有字符。

除了单线模式,
将匹配除
\n
之外的所有字符。
正如您所注意到的,它确实匹配
\r


我不知道为什么。

好吧,我不认为“雷德蒙州有什么烂东西!”,至少你的情景并不能证明这一点。但我确实认为这种行为不是一个bug,而是一个特性。为什么?仅仅因为Perl正则表达式具有相同的行为(我刚刚检查过),而且我相信PHP的PCREs(Perl兼容的正则表达式)也具有相同的行为。MS只是让他们的正则表达式方法的行为方式与事实上的经典Perl方法相同。现在我的问题是:“JS王国出了什么问题?”:)

我想这里的要点是点应该匹配任何不是线分隔符的东西,而
\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
3
4
7
^
$
三个行分隔符都能正常工作。现在用C#试试:

结果:

3
3
3
3
3
4
7

这对其他人来说合适吗?在这里,我们将regex风格内置到Microsoft的.NET框架中,它甚至不能正确处理Windows标准行分隔符。与其他Unicode行分隔符一样,它完全忽略了一个单独的
\r
。NET在Java之后出现了几年,其Unicode支持至少也一样好,那么他们为什么选择坚持这一点?

并再次删除它,没有明显的原因?我删除的答案不是一个解决方案。我试过了,但它没有改变任何东西。那是因为单线使人兴奋。匹配一切。OP希望它与Lazarus的[^\r\n]+1相等。看起来grep和grep-E的行为方式是一样的。你可能认为使用RegexOptions.ECMAScript会有所帮助,但它仍然失败。@Steve Wortham:“包括在其他实现中尚未看到的功能,例如从右到左匹配和动态编译”--他,Perl正则表达式在默认情况下是预编译的,并且早在.NET出现之前就进行了动态编译existence@Igor:他们所说的是使用
Compiled
选项在CLR(CLI?)字节码中为该正则表达式创建一个单独的类。它甚至可以保存在自己的DLL中。结果比一个简单的正则表达式对象快得多,但是如果正则表达式不经常使用,编译它所涉及的开销往往会抵消这一优势