我想为脚本引擎验证一些C#源代码。我想确保只能引用System.Math类成员。我正在尝试创建一个正则表达式,它将匹配一个点,后跟一个大写字母,后跟任意数量的单词字符,以一个不在System.Math之前的单词边界结束。
我从这开始:
(?<!Math)\.[A-Z]+[\w]*
适用于:
return Math.Max(466.89/83.449 * 5.5); // won’t flag this
return Xath.Max(466.89/83.449 * 5.5); // will flag this
当它没有Math之前正确匹配.Max。但是,现在我正在尝试将正则表达式扩展为包含System,我无法让它工作。
我已经尝试了正则表达式的这些排列以及更多:
((?<!System\.Math)\.[A-Z]+[\w]*)
((?<!(?<!System)\.Math)\.[A-Z]+[\w]*)
((?<!System)\.(?<!Math)\.[A-Z]+[\w]*)
((?<!System)|(?<!Math)\.[A-Z]+[\w]*)
((?<!System\.Math)|(?<!Math)\.[A-Z]+[\w]*)
使用这些陈述:
return System.Math.Max(466.89/83.449 * 5.5);
return System.Xath.Max(466.89/83.449 * 5.5);
return Xystem.Math.Max(466.89/83.449 * 5.5);
我已经尝试了所有我能想到的东西,但它总是匹配第二个元素(上面的.Math或.Xath),或者它与任何东西都不匹配。
如果有人愿意怜悯我并指出我做错了什么,我会非常感激。
提前致谢, 慧通
答案 0 :(得分:2)
如果您只是在寻找示例中所说的内容,那么这个正则表达式就可以了。
^[\w\s]*?[A-Z]\w+\.[A-Z]\w+\.(?<!System\.Math\.)
它匹配除System.Math.XXX之外的所有其他呼叫,只要:a)呼叫中有两个.
,b)呼叫在一行上。
return System.Math.Max(466.89/83.449 * 5.5); // no match
return System.Xath.Max(466.89/83.449 * 5.5); // match
return Xystem.Math.Max(466.89/83.449 * 5.5); // match
System.Math.Max(466.89/83.449 * 5.5); // no match
System.Xath.Max(466.89/83.449 * 5.5); // match
Xystem.Math.Max(466.89/83.449 * 5.5); // match
return System.Math.Max(466.89/83.449 * 5.5); // no match
return System.Xath.Max(466.89/83.449 * 5.5); // match
return Xystem.Math.Max(466.89/83.449 * 5.5); // match
Math.Max(466.89/83.449 * 5.5); // no match - only one '.'
System.Max.Math(466.89/83.449 * 5.5); // match
我同意这些意见;任何正则表达式都非常脆弱,只能被视为文本编辑器类型的帮助。如果你希望它是防弹,你需要一个解析器。
答案 1 :(得分:2)
诀窍是确保你从不在任何地方开始匹配成员名称。然后,使用前瞻来查明你所看到的内容是否以System.Math.
开头是一件简单的事情。试试这个正则表达式:
(?<![\w.])(?!(?:System\.)?Math\.)(?:[A-Z]\w*\.)+[A-Z]\w*\b
lookbehind确保匹配不会在单词(\w
)的中间或合格成员名称(.
)的中间开始。现在,如果前瞻失败,它不能只跳到下一个组件的开头(例如Math.
中的System.Math.
)并再试一次。这是全有或全无。
但是,如果前面没有Math.Max
,则此将匹配System.
。你真的需要它,还是只是为全名开发正则表达式的中间步骤?
编辑:我继续前进,使System.
部分可选。