2012-03-13 71 views
5

我试图想出一个正则表达式来从SQL语句中删除评论。从SQL语句中删除评论的正则表达式

这几乎正则表达式的工作原理:

(/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/)|'(?:[^']|'')*'|(--.*) 

Excepth半句不处理 “ - ” 很好的意见。问题在于处理用''分隔的SQL字符串。

举例来说,如果我有

SELECT ' -- Hello -- ' FROM DUAL 

应该无法比拟的,但它的匹配。

这是在ASP/VBscript。

我想过从右到左匹配,但我不认为VBScript的正则表达式引擎支持它。也尝试过负面的逆序,但结果并不好。

回答

1

正如你所说,你的正则表达式的其余部分是好的,我专注于最后一部分。所有你需要做的就是验证--为开头,然后确保它会删除所有破折号,如果有超过2结束正则表达式低于

(^[--]+) 

以上仅仅是,如果你想删除评论破折号而不是整行。您可以运行下面的,如果你想后,一切该行的结束,也

(^--.*) 
+0

贾斯汀嗨,你好,感谢您的帮助。内嵌评论的问题仍然存在,一开始就没有开始。就像SELECT' - Hello - 'FROM DUAL - 应该删除的注释 – 2012-03-14 14:04:30

+0

没问题,并欢迎堆栈溢出。请记住,在这里表示赞赏的方式是通过upvotes和接受的答案(答案旁边的复选标记)。更多信息可以在[常见问题解答]中找到,尤其是[FAQ#HowToAsk]如何提问 – 2012-03-14 14:09:29

4

在PHP中,我使用这个代码取消注释SQL:

$sqlComments = '@(([\'"]).*?[^\\\]\2)|((?:\#|--).*?$|/\*(?:[^/*]|/(?!\*)|\*(?!/)|(?R))*\*\/)\s*|(?<=;)\[email protected]'; 
/* Commented version 
$sqlComments = '@ 
    (([\'"]).*?[^\\\]\2) # $1 : Skip single & double quoted expressions 
    |(     # $3 : Match comments 
     (?:\#|--).*?$ # - Single line comments 
     |    # - Multi line (nested) comments 
     /\*    # . comment open marker 
      (?: [^/*] # . non comment-marker characters 
       |/(?!\*) # . ! not a comment open 
       |\*(?!/) # . ! not a comment close 
       |(?R) # . recursive case 
      )*   # . repeat eventually 
     \*\/    # . comment close marker 
    )\s*     # Trim after comments 
    |(?<=;)\s+   # Trim after semi-colon 
    @msx'; 
*/ 
$uncommentedSQL = trim(preg_replace($sqlComments, '$1', $sql)); 
preg_match_all($sqlComments, $sql, $comments); 
$extractedComments = array_filter($comments[ 3 ]); 
var_dump($uncommentedSQL, $extractedComments); 
+0

这很好,但我不喜欢最后的修剪,因为它可以删除可能真正需要/必要的换行符当代码之后的内联注释在它之前没有空间时...人们这样做:|)。还添加反引号到报价单。所以我使用: $ sqlComments ='@(([\'“'])。*?[^ \\\] \ 2)|((?:\#| - )。*?$ |/* *(?:[^/*] | /(!!\ *)| \ *(?!/)|(?R))* \ * \ /)+ @ ms'; – dkloke 2014-12-07 05:55:31

+0

This regexp segfaults PHP的5.6)或返回NULL(PHP 7 +)与开始长评论的查询,例如 ' /*放在这里8kb的虚拟文本*/ 选择1; ' – 2017-08-12 02:44:13

+0

我跑了120K查询通过这个正则表达式和它在检测查询过程中有一些主要的缺陷,例如正确封装的包含“ - ”(双短横线)的字符串被移除 – 2017-08-15 18:31:00

1

此代码工作对我来说:

function strip_sqlcomment ($string = '') { 
    $RXSQLComments = '@(--[^\r\n]*)|(\#[^\r\n]*)|(/\*[\w\W]*?(?=\*/)\*/)@ms'; 
    return (($string == '') ? '' : preg_replace($RXSQLComments, '', $string)); 
} 

一点点正则表达式调整它可以用任何语言

0

原剥离评论我使用了@Adrien Gibrat的解决方案。但是,我遇到了一个情况,那就是它没有正确解析引用的字符串,如果我在它们之内有前面的' - '的话。我写了这个,而不是:

'[^']*(?!\\)'(*SKIP)(*F)  # Make sure we're not matching inside of quotes 
|(?m-s:\s*(?:\-{2}|\#)[^\n]*$) # Single line comment 
|(?: 
    \/\*.*?\*\/     # Multi-line comment 
    (?(?=(?m-s:\h+$))   # Get trailing whitespace if any exists and only if it's the rest of the line 
    \h+ 
) 
) 

# Modifiers used: 'xs' ('g' can be used as well, but is enabled by default in PHP) 

请注意,这应该使用PCRE时可用。所以,就我而言,我在我的PHP库中使用了这种变体。

Example

+1

这太棒了!我更新了正则表达式,因此它忽略了不仅在单引号中的注释,而且还包含双引号和反引号 - https://regex101.com/r/GXb0a5/2 – 2017-08-12 03:04:35

0

请参阅我的回答here。它适用于行注释块注释,甚至嵌套块注释。我想你需要使用正则表达式与平衡组,其中AFAIK在VBScript中不可用。

-1

对于所有PHP人员:请使用此库 - https://github.com/jdorn/sql-formatter。我一直在处理几年来从SQL中剥离注释的问题,唯一有效的解决方案是一个令人信服的标记器/状态机器,我懒洋洋地拒绝写这个机器。几天前我发现了这个lib,并通过它运行了12万次查询,发现只有一个bug(https://github.com/jdorn/sql-formatter/issues/93),它立即在我们的分支https://github.com/keboola/sql-formatter中修复。

的用法很简单

$query <<<EOF 
/* 
    my comments 
*/ 
SELECT 1; 
EOF; 

$bareQuery = \SqlFormatter::removeComments($query); 
// prints "SELECT 1;" 
print $bareQuery; 
+0

@BaummitAugen谢谢,修复了答案。 – 2017-08-15 23:12:03