2012-03-13 42 views
5

Estoy tratando de encontrar una expresión regular para eliminar comentarios de una declaración SQL.Expresión regular para eliminar comentarios de la declaración SQL

Esta expresión regular casi funciona:

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

Excepth esa última parte no maneja "-" comentarios muy bien. El problema es el manejo de cadenas SQL, delimitadas con ''.

Por ejemplo, si tengo

SELECT ' -- Hello -- ' FROM DUAL 

No debe coincidir, pero está a juego.

Esto está en ASP/VBscript.

He pensado en hacer coincidir de derecha a izquierda, pero no creo que el motor de expresiones regulares de VBScript lo admita. También traté de jugar con lookbehind negativo, pero los resultados no fueron buenos.

Respuesta

1

Como dijiste que el resto de tu expresión regular está bien, me centré en la última parte. Todo lo que necesita hacer es verificar que el -- es al principio y después asegurarse de que elimina todos los guiones si hay más de 2. La expresión regular final está por debajo de

(^[--]+) 

Lo anterior es sólo si desea eliminar el comentario se lanza y no toda la línea. Puede ejecutar el siguiente si quiere que todo después de que al final de la línea, también

(^--.*) 
+0

Hola Justin ... gracias por la ayuda. Todavía queda el problema con los comentarios en línea que no comienzan al principio. Como SELECCIONAR '- Hola -' DE DUAL - comentario que debe eliminarse –

+0

No hay problema, y ​​bienvenido al desbordamiento de la pila. Por favor, recuerde que la forma de demostrar aprecio aquí es a través de votaciones y respuestas aceptadas (marca de verificación al lado de la respuesta). Se puede encontrar más información en [Preguntas frecuentes], especialmente [Pregunta frecuente Preguntas frecuentes] Cómo preguntar –

4

En PHP, estoy usando este código para SQL uncomment:

$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

Esto es estelar pero no me gustó el recorte al final, porque puede eliminar las nuevas líneas que en realidad podrían ser deseables/necesarias (como cuando un comentario en línea después del código no tiene espacio antes ... la gente hace esto: |). También se agregaron los backticks a la lista de presupuestos. Así que estoy usando: $ sqlComments = '@ (([\' "']). *? [^ \\\] \ 2) | ((?: \ # | -). *? $ |/\ * (?: [^/*] |/(?! \ *) | \ * (?! /) | (? R)) * \ * \ /) + @ ms '; – dkloke

+0

Esta regexp segfaults (PHP 5.6) o devuelve NULL (php 7+) en las consultas con los comentarios largos al principio, por ejemplo ' /* poner aquí de 8 kb del texto de relleno */ seleccione 1; ' –

+0

corrí alrededor de 120k consultas a través de esta expresión regular y tiene algunos defectos importantes en la detección de comentarios en el medio de una consulta. Por ejemplo, las cadenas adecuadamente encapsuladas que contienen "-" (cadena de doble guión) se eliminan. –

1

Este código funciona para mí:

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

con un poco de expresiones regulares tweak que podría ser utilizado para despojar a los comentarios en cualquier idioma

0

original Entonces, utilicé la solución de @Adrien Gibrat. Sin embargo, me encontré con una situación en la que no estaba analizando cadenas citadas, correctamente, si tenía algo con un '-' precedente dentro de ellas. Terminé de escribir esto, en lugar:

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

Tenga en cuenta que esto se debe utilizar cuando PCRE está disponible. Entonces, en mi caso, estoy usando una variación de esto en mi biblioteca de PHP.

Example

+1

¡Esto es dulce! He actualizado la expresión regular por lo que ignora los comentarios no solo en comillas simples, sino también en comillas dobles y retrocesos - https://regex101.com/r/GXb0a5/2 –

0

Por favor, vea mi respuesta here. Funciona tanto para comentarios de línea como para comentarios de bloque, incluso comentarios de bloque anidado. Supongo que debe usar expresiones regulares con grupos de balanceo, que AFAIK no está disponible en VBScript.

-1

Para todos los usuarios de PHP: utilicen esta biblioteca - https://github.com/jdorn/sql-formatter. Me he estado ocupando de eliminar comentarios de SQL durante un par de años y la única solución válida sería una máquina tokenizador/estado, que me resistí a escribir.Hace un par de días descubrí esta lib y ejecuté 120k consultas a través de ella y encontré solo un error (https://github.com/jdorn/sql-formatter/issues/93), que se soluciona de inmediato en nuestro tenedor https://github.com/keboola/sql-formatter.

El uso es simple

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

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

@BaummitAugen Gracias, corrigió la respuesta. –

Cuestiones relacionadas