为什么这个正则表达式适用于JavaScript,而不是C#?

Ric*_*ard 4 c# regex

表达

var regex = new Regex(@"{([A-z]*)(([^]|:)((\\:)|[^:])*?)(([^]|:)((\\:)|[^:])*?)}");
Run Code Online (Sandbox Code Playgroud)

分解

表达式[粗略地]设计为使用以下格式在输入中查找标记:{name[:pattern[:format]]},其中patternformat是可选的.

{
  ([A-z]*) // name
  (([^]|:)((\\:)|[^:])*?) // regex pattern
  (([^]|:)((\\:)|[^:])*?) // format
}
Run Code Online (Sandbox Code Playgroud)

此外,表达式尝试忽略转义冒号,从而允许使用诸如的字符串 {Time:\d+\:\d+\:\d+:hh\:mm\:ss}

当测试RegExr.com,一切工作充分,试图在C#中相同的图案然而,当,输入匹配失败,为什么?

(对表达式进行一般改进的任何建议也非常受欢迎)

Wik*_*żew 6

[^]模式仅在JavaScript中有效,它与非任何内容匹配,即任何字符(尽管在ES5中,它与BMP平面外的字符不匹配).在C#中,很容易匹配任何char .并传递RegexOptions.Singleline 修饰符.但是,在JS中,不支持修饰符,但您可以将任何char与[\s\S]变通方法模式匹配.

因此,为了使两种正则表达式兼容而需要进行的最小更改是更改([^]|:)为,[\s\S]因为不需要使用a : 作为替代(因为[\s\S]已经匹配冒号).

另外,请勿将其[A-z]用作匹配ASCII字母的快捷方式.使用[a-zA-Z][a-z]传递不区分大小写的修饰符.

所以,您可以考虑将表达式编写为

{([A-Za-z]*)([\s\S]((\\:)|[^:])*?)([\s\S]((\\:)|[^:])*?)}
Run Code Online (Sandbox Code Playgroud)

查看.NET正则表达式测试JS正则表达式测试.

当然,这里可能还有其他增强功能:删除多余的组,添加对任何转义序列的支持(不仅仅是转义的冒号)等,但它不属于问题范围.