EOL特殊字符不匹配

问题描述:

我试图在输入字符串中找到每个“a→b,c,d”模式。 我使用的图案是这样的:EOL特殊字符不匹配

"^[ \t]*(\\w+)[ \t]*->[ \t]*(\\w+)((?:,[ \t]*\\w+)*)$" 

该图案是一个C#图案中,“\ t”的是指一种制表(其单个转义litteral,由.NET字符串API intepreted),则“\ w”指的是众所周知的正则表达式的预定义类,双重转义为由.NET STring API解释为“\ w”,然后由.NET Regex API作为“WORD CLASS”解释。

输入是:

a -> b 
b -> c 
c -> d 

功能是:

private void ParseAndBuildGraph(String input) { 
    MatchCollection mc = Regex.Matches(input, "^[ \t]*(\\w+)[ \t]*->[ \t]*(\\w+)((?:,[ \t]*\\w+)*)$", RegexOptions.Multiline); 
    foreach (Match m in mc) { 
     Debug.WriteLine(m.Value); 
    } 
} 

输出是:

c -> d 

其实,有结尾 “$” 就行了问题特殊字符。如果我在“$”之前插入“\ r”,它会起作用,但我认为“$”将匹配任何行终止符(使用多行选项),尤其是Windows环境中的\ r \ n。情况不是这样吗?

这让我吃惊了。在.NET正则表达式中,$行分隔符之前不匹配,它匹配换行 - 字符\n。这种行为与Perl的正则表达式一致,但在我看来,它仍然是错误的。 According to the Unicode standard$任何之前应符合:

\n\r\n\r\x85\u2028\u2029\v\f

...永不\r\n之间的匹配。 Java符合该规范(除\v\f之外),但.NET在Java之后出现并且其Unicode支持至少与Java一样好,但仅支持\n。考虑到微软与该行分隔符的关联程度,你会认为他们至少能正确处理\r\n

注意.遵循相同的模式:它不匹配\n(除非单线模式设置),但它确实比赛\r。如果你在你的regex中使用了.+而不是\w+,你可能没有注意到这个问题。回车符将被包含在比赛中,但控制台在打印结果时会忽略它。

编辑:如果你想允许回车而不将它包含在你的结果中,你可以用一个前视图代替锚点:(?=\r?\n

+1

+1这很难相信... – 2010-03-19 22:06:41

+0

谢谢你的回答。事实上,这是一个令人惊讶的结论:) – 2010-03-19 23:09:29

+0

好奇,如果有一个标志,可以设置为使系统匹配数据,如在C/C + +中的O_BINARY标志。 – Dave 2010-03-20 00:55:43

你的意思是\t作为正则表达式\t或C#\t?我总是用逐字字符串与正则表达式:

@"^[ \t]*(\w+)[ \t]*->[ \t]*(\w+)(,[ \t]*\w+)*$" 

(你需要逃跑的唯一的事情就是"""

+0

其实\ t是指一个制表。我不想使用\\ s作为空白字符,因为我不希望用户输入行尾,只允许使用空格和制表符。 但我的问题仍然与简化模式“^(\\ w +) - >(\\ w +)((?:,\\ w +)*)$”一样。我更新了原来的问题。 – 2010-03-19 21:23:07

+0

@Aurélien - 是的,但没有逐字字符串字面值正则表达式在* all *处看不到'\ t'。 2010-03-19 22:09:34

+0

@Marc Gravell - 它是一个制表符或空格选项,除非正则表达式不允许嵌入制表符,他字面意思是制表符,而不是\ t – Guvante 2010-03-19 22:17:51

通常在C,C++,C#中,程序中的字符串使用“\ n”作为行分隔符。如果打开textmode转换,“\ r \ n”仅出现在I/O层。

+0

好点。我总是很惊讶这个问题很少出现,我想这就是其中一个原因。但我仍然认为他们错误地不遵循Unicode标准。 – 2010-03-19 23:08:21

+0

\ r \ n是Microsoft行终止。例如,Notepad.exe不识别“\ n”终止,并且只识别“\ r \ n”。对于Unix用户来说,“\ n”是通常的线路终端,对于Mac用户来说,“\ r”是最好的选择。这是一个愚蠢的混乱?我同意:-) – 2010-03-19 23:14:24

+0

\ r \ n是文本文件中的行结束符(在Windows中)。 \ n是代码中的终止符。当且仅当您以“文本模式”打开文件时,I/O层才会在它们之间进行转换。 – 2010-03-20 03:04:15