Regex, чтобы соответствовать комментариям MySQL - PullRequest
1 голос
/ 18 августа 2011

Мне нужно найти и удалить все комментарии из запроса MySQL.Проблема, которую я имею, состоит в том, чтобы избежать маркеров комментариев (-, #, / * ... * /), которые находятся внутри кавычек или обратных кавычек.

Ответы [ 5 ]

6 голосов
/ 11 декабря 2012

В PHP я использую этот код для раскомментирования SQL:

$sqlComments = '@(([\'"`]).*?[^\\\]\2)|((?:\#|--).*?$|/\*(?:[^/*]|/(?!\*)|\*(?!/)|(?R))*\*\/)\s*|(?<=;)\s+@ms';
/* Commented version
$sqlComments = '@
    (([\'"`]).*?[^\\\]\2) # $1 : Skip single & double quoted + backticked 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 );
3 голосов
/ 18 августа 2011

К сожалению, то, что вы пытаетесь сделать, требует грамматики без контекста и не может быть сделано с помощью регулярного выражения. Это из-за вложенности, а в теории компьютерных наук нам требуется стек, чтобы отслеживать, когда вы вложены в кавычки или что-то нет. (С технической точки зрения для этого требуется обычный автомат, а не обычный язык. Бла-бла, академия-бла ...) Это не сложно реализовать, но это нужно делать процедурно, и, честно говоря, это может потребовать больше усилий, чем вы хотите израсходовать.

Если вы не против вырезать и вставлять, вы можете использовать SQLInform . Онлайн-режим бесплатный и поддерживает удаление комментариев.

UPDATE

Учитывая комментарий, который я получил ниже, я поиграл с редактором MySQL. Я ошибся - они фактически запретили вложение чего-то более глубокого, чем один уровень. Вы больше не можете вкладывать комментарий внутри комментария (если вы когда-либо могли). В любом случае я оставлю свой ответ только для ссылки SQLInform.

0 голосов
/ 20 августа 2014

Этот код работает для меня:

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

с небольшой настройкой регулярных выражений, его можно использовать для удаления комментариев на любом языке

0 голосов
/ 05 января 2013

К сожалению, вы можете выполнять очень ограниченное форматирование SQL только с помощью регулярных выражений.Основная причина в том, что есть, например, комментарии, которые вы не хотите удалять, или токены, которые нельзя вводить в нижнем / верхнем регистре, поскольку они являются частью литерала, и не всегда легко найти начало и конец литералов как различные диалекты SQLиспользуйте различные символы, а иногда даже несколько символов, чтобы заключить литерал.Иногда люди помещают кусочки SQL в комментарии для последующего повторного использования.Вы не хотите переформатировать эти части SQL.Когда вы изменяете оператор SQL с помощью регулярного выражения, снова запустите измененный SQL в инструменте БД, чтобы убедиться, что вы ничего не изменили в логике.Я слышал о людях, которые запускают регулярные выражения в сотнях файлов SQL без проверки результатов.Я думаю, что это очень опасный шаг.Никогда не меняйте работающий SQL ;-)

0 голосов
/ 21 августа 2011

Кто-то написал это для вас. Конвертировать на любой язык, который вам требуется.

Использование регулярных выражений для очистки операторов SQL

Вот перевод C #, включенный в ответ на тот случай, если исходная ссылка исчезнет. Я не проверял это, но выглядит хорошо.

public static string ToRaw(string commandText)
{
    RegexOptions regExOptions = (RegexOptions.IgnoreCase | RegexOptions.Multiline);
    string rawText=commandText;
    string regExText = @”(‘(”|[^'])*’)|([\r|\n][\s| ]*[\r|\n])|(–[^\r\n]*)|(/\*[\w\W]*?(?=\*/)\*/)”;
    //string regExText = @”(‘(”|[^'])*’)|[\t\r\n]|(–[^\r\n]*)|(/\*[\w\W]*?(?=\*/)\*/)”;
    //’Replace Tab, Carriage Return, Line Feed, Single-row Comments and
    //’Multi-row Comments with a space when not included inside a text block.

    MatchCollection patternMatchList = Regex.Matches(rawText, regExText, regExOptions);
    int iSkipLength = 0;
    for (int patternIndex = 0; patternIndex < patternMatchList.Count; patternIndex++)
    {
        if (!patternMatchList[patternIndex].Value.StartsWith("'") && !patternMatchList[patternIndex].Value.EndsWith("'"))
        {
            rawText = rawText.Substring(0, patternMatchList[patternIndex].Index – iSkipLength) + " " + rawText.Substring(patternMatchList[patternIndex].Index – iSkipLength + patternMatchList[patternIndex].Length);
            iSkipLength += (patternMatchList[patternIndex].Length – " ".Length);
        }
    }
    //'Remove extra spacing that is not contained inside text qualifers.
    patternMatchList = Regex.Matches(rawText, "'([^']|'')*'|[ ]{2,}", regExOptions);
    iSkipLength = 0;
    for (int patternIndex = 0; patternIndex < patternMatchList.Count; patternIndex++)
    {
        if (!patternMatchList[patternIndex].Value.StartsWith("'") && !patternMatchList[patternIndex].Value.EndsWith("'"))
        {
            rawText = rawText.Substring(0, patternMatchList[patternIndex].Index – iSkipLength)+" " + rawText.Substring(patternMatchList[patternIndex].Index – iSkipLength + patternMatchList[patternIndex].Length);
            iSkipLength += (patternMatchList[patternIndex].Length – " ".Length);
        }
    }
    //'Return value without leading and trailing spaces.
    return rawText.Trim();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...