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

时间:2017-08-22 16:49:48

标签: c# regex

表达式

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

击穿

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

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

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

问题

RegExr.com上进行测试时,一切都充分,但是当在C#中尝试相同的模式时,输入无法匹配,为什么?

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

1 个答案:

答案 0 :(得分:6)

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

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

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

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

{([A-Za-z]*)([\s\S]((\\:)|[^:])*?)([\s\S]((\\:)|[^:])*?)}

查看.NET regex testJS regex test

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