我已经尝试过寻找答案的解决方案但是只找到了在两个字符串之间进行搜索的一般问题。
基本上我试图找到任何不用于在SQL脚本中创建表的SELECT语句。
我目前在Sublime Text 3中使用此正则表达式:;(\h|\v|/\*(?s).+?\*/)+((SELECT|SEL)(?s).+?;)
重点是找到一个在";"之后发生的SELECT语句。可以有垂直空格,水平空格或中间的注释块。
当注释块之间存在某些内容时,此操作无效。例如
;
/*Comment Block*/
CREATE TABLE table AS SELECT * FROM other_table1 AS a INNER JOIN (
/*Comment Block*/
SELECT *
FROM other_table2
) AS b
ON a.key = b.key
;
将匹配,因为从技术上讲,CREATE TABLE位于/ *和* /之间。我尝试使比赛非贪婪,如果我只使用正则表达式/\*(?s).+?\*/
,那就有效。它一次只能选择一个注释块,但是当与OR运算符一起使用时,#34; |" (对不起,如果这不是技术上称为操作员),它似乎很贪婪。
关于如何解决此问题的任何想法?
答案 0 :(得分:0)
(s).+?/\*
懒惰地匹配所有字符,包括新行,直到找到/*
。一旦正则表达式引擎找到第一个注释块的结尾,它就会继续匹配SELECT
,但它不能。由于它是一个懒惰的搜索,它会放弃任何进一步的搜索,如果它找到SELECT
,但它不会因此回溯并继续。然后它找到第二个注释块的结尾,之后它可以找到SELECT
。
对你的正则表达式展示的根本误解是使用懒惰匹配,你需要一个非回溯匹配。懒惰并不意味着不会发生回溯。懒惰意味着没有不必要的回溯发生。
避免回溯的方法是使用原子团,例如: (?>example atomic group)
。然后你的正则表达式成为:
;(?>\h|\v|/\*(?s).+?\*/)+((SELECT|SEL)(?s).+?;)
请参阅action。
避免此问题的另一种方法是避免搜索注释块中的所有字符。实现此目的的方法(显然)是匹配所有不以*
开头的字符,后跟注释块中的/
。这转换为([^*]|\*(?=/))+
。然后你的正则表达式成为:
;(\h|\v|/\*([^*]|\*(?=/))+\*/)+((SELECT|SEL)(?s).+?;)