2012-11-26 140 views
2

我们在更多面向SQL的项目之一中使用RoundhousE迁移工具。我有胡茬在一个非常奇怪的错误无限循环与正则表达式

某SQL函数脚本(遗憾的是我不能提供脚本,因为我的客户的财产),使正则表达式的替换方法永远不会返回

正则表达式看起来像这样

(?<KEEP1>^(?:[\s\t])*(?:-{2}).*$)|(?<KEEP1>/{1}\*{1}[\S\s]*?\*{1}/{1})|(?<KEEP1>'{1}(?:[^']|\n[^'])*?'{1})|(?<KEEP1>\s)(?<BATCHSPLITTER>GO)(?<KEEP2>\s)|(?<KEEP1>\s)(?<BATCHSPLITTER>GO)(?<KEEP2>$) 

在RounhousE的代码行不会返回

string sql_statement_scrubbed = regex_replace.Replace(sql_to_run, match => evaluate_and_replace_batch_split_items(match, regex_replace)); 

的问题是不是在委托evaluate_and_replace_batch_split_items它在实际的regex.Replace方法中,我尝试了一个简单的正则表达式工具中的正则表达式,它也挂起。也许有人在RegEx上是一位大师,可以看出问题所在?

编辑:如果我从这个SQL注释-- If no previous, don't report revised 它的工作原理,但去掉(撇号),其不仅以它必须有其他的文字脚本的组合,因为这条线运行在拥有

+0

它看起来像在您的评论的撇号被莫名其妙地解释为引用字符串的开始,和正则表达式需要永远为该“字符串”找到相应的结束引号。我的正则表达式(见下文)不应该受到这种情况可能带来的复杂度的指数增长的影响,但它仍然可以匹配错误的文本 - 因此一个问题:是否可以存在多行字符串,即i。即一个以'''开头并以'''结尾但在两者之间包含换行符的字符串? –

+0

错过了这个评论,可能你可能有'我不喜欢这个synstax'和换行 – Anders

+0

所以实质上,无效的字符串(因为你不能在一个字符串中使用撇号来限定撇号)?然后,正则表达式将失败,就像任何语言解析器会因语法错误而失败一样。 –

回答

2

通常,当正则表达式需要永远匹配(或者更可能发现它不匹配)时,这是因为灾难性的回溯。在正则表达式中有几个实例可能会出现这种情况,具体取决于您的输入是什么样的。我已经把你的正则表达式清理了一下,删除了大量不必要的量词和变化。此正则表达式:

(?<KEEP1>^\s*--.*$)|(?<KEEP1>/\*[\S\s]*?\*/)|(?<KEEP1>'[^']*')|(?<KEEP1>\s)(?<BATCHSPLITTER>GO)(?<KEEP2>\s|$) 

将匹配完全相同的,因为原有的正则表达式,但它的复杂性更低,应该更加稳定。请试一试。

要正确处理转义撇号的字符串中('It\'s something else!'),你就需要改变正则表达式:

(?<KEEP1>^\s*--.*$)|(?<KEEP1>/\*[\S\s]*?\*/)|(?<KEEP1>'(?:\\.|[^'\\])*')|(?<KEEP1>\s)(?<BATCHSPLITTER>GO)(?<KEEP2>\s|$) 
+0

会做谢谢! – Anders

+0

它的工作原理! :D您是否希望将荣誉转交给RoundhousE或者我应该这样做? – Anders

+0

@Anders:很高兴听到它。我不知道什么是RoundhousE,所以我猜这样做会更好:) –