2012-03-13 13 views
5

Próbuję wymyślić wyrażenie regularne, aby usunąć komentarze z instrukcji SQL.Wyrażenie regularne służące do usuwania komentarzy z instrukcji SQL

Ten regex prawie działa:

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

Excepth że ostatnia część nie obsługuje "-" komentarze bardzo dobrze. Problemem jest obsługa łańcuchów SQL ograniczonych przez ''.

Na przykład, jeśli mam

SELECT ' -- Hello -- ' FROM DUAL 

Nie powinien pasować, ale to dopasowanie.

To jest w ASP/VBscript.

Myślałem o dopasowaniu od prawej do lewej, ale nie sądzę, że silnik regex VBScript obsługuje to. Próbował także bawić się z negatywnym lookbehindem, ale wyniki nie były dobre.

Odpowiedz

1

Tak jak powiedziałeś, że reszta twojego regex jest w porządku, skupiłem się na ostatniej części. Wszystko, co musisz zrobić, to upewnić się, że -- jest na początku, a następnie upewnij się, że usuwa wszystkie kreski, jeśli istnieje więcej niż 2. Koniec regex jest poniżej

(^[--]+) 

powyższe jest tylko jeśli chcesz usunąć komentarz pauzuje, a nie całą linię. Można uruchomić poniżej jeśli chcesz wszystko po to, aby na końcu linii, również

(^--.*) 
+0

Cześć Justin ... dzięki za pomoc. Nadal pozostaje problem z komentarzami wstawionymi, które nie rozpoczynają się na początku. Jak SELECT "- Hello -" FROM DUAL - komentarz, który powinien zostać usunięty –

+0

Nie ma problemu i zapraszam do przepełnienia stosu. Pamiętaj, że sposób, w jaki można to docenić, polega na przegrywaniu i zaakceptowaniu odpowiedzi (zaznaczenie obok odpowiedzi). Więcej informacji można znaleźć w [Najczęściej zadawanych pytaniach], szczególnie [FAQ # HowToAsk] How To Ask –

4

w PHP, używam tego kodu do Odkomentuj 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

To jest gwiezdne, ale nie podobało mi się przycinanie na końcu, ponieważ może usunąć nowe linie, które mogą być pożądane/konieczne (jako kiedy wstawiony komentarz po kodzie nie ma spacji przed nim ... ludzie robią to: |). Dodano też linki do listy cytowań. Używam: $ sqlComments = '@ (([\' "']). *? [^ \\\] \ 2) | ((?: \ # | -). *? $ |/\ * (?: [^/*] |/(?! \ *) | \ * (?! /) | (? R)) * \ * \ /) + @ ms '; – dkloke

+0

To wyrażenie segfaults (PHP 5.6) lub zwraca NULL (php 7+) na zapytaniami o długich komentarzach na początku, np ' /* umieścić tutaj 8 kb tekstu manekina */ wybierz 1; ' –

+0

wpadłem około 120k zapytań przez ten regexp i ma kilka poważnych wad w wykrywaniu komentarzy w środku zapytania, np. poprawnie zamknięte ciągi zawierające "-" (podwójny ciąg myślnikowy) są usuwane –

1

ten kod działa dla mnie:

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

z odrobiną regex dostrojenia może on być wykorzystany do paska komentarzy w dowolnym języku

0

Original ly, użyłem rozwiązania @Adrien Gibrat. Jednak natknąłem się na sytuację, w której nie analizowałem cytowanych ciągów, właściwie, gdybym miał coś z poprzedzającym "-" wewnątrz nich. Później napisałem to:

'[^']*(?!\\)'(*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) 

Należy pamiętać, że powinno to być używane, gdy PCRE jest dostępny. Tak więc w moim przypadku używam odmiany tego w mojej bibliotece PHP.

Example

+1

To jest słodkie! Zaktualizowałem wyrażenie regularne, aby ignorować komentarze nie tylko w pojedynczych cudzysłowach, ale także w podwójnych cudzysłowach i odsyłaczach - https://regex101.com/r/GXb0a5/2 –

0

proszę zobaczyć moją odpowiedź here. Działa zarówno dla komentarzy , jak i dla komentarzy blokowych, nawet zagnieżdżonych komentarzy blokowych. Przypuszczam, że musisz użyć regex z grupami bilansującymi, których AFAIK nie jest dostępny w VBScript.

-1

Dla wszystkich użytkowników PHP: skorzystaj z tej biblioteki - https://github.com/jdorn/sql-formatter. Miałem do czynienia z usuwaniem komentarzy z SQL od kilku lat i jedynym właściwym rozwiązaniem byłby tokenizer/automat stanów, który leniwie opierałem się pisaniu.Kilka dni temu znalazłem tę bibliotekę i przetestowałem 120k zapytań i znalazłem tylko jeden błąd (https://github.com/jdorn/sql-formatter/issues/93), który jest natychmiast naprawiany w naszym widelcu https://github.com/keboola/sql-formatter.

Użycie jest proste

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

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

@BaummitAugen Dzięki, poprawiono odpowiedź. –

Powiązane problemy