2010-08-25 15 views
5

tengo esta cadena aquí:¿Tiene Regex que ignore las nuevas líneas y solo coincida con una cadena grande?

CREATE UNIQUE INDEX index555 ON 
SOME_TABLE 
(
    SOME_PK   ASC 
); 

Quiero coincidir a través de las múltiples líneas y combinar las sentencias SQL (todos ellos, habrá muchos en 1 cadena grande) ... algo como esto, sin embargo yo sólo estoy haciendo un partido en CREATE UNIQUE INDEX index555 ON

(CREATE\s.+;) 

nota: estoy tratando de lograr esto en java si importa.

Respuesta

13

Es necesario utilizar dotall y banderas de varias líneas cuando la compilación de una expresión regular. Aquí está un ejemplo de código Java:

import java.util.regex.*; 

public class test 
{ 
    public static void main(String[] args) 
    { 
     String s = 
     "CREATE UNIQUE INDEX index555 ON\nSOME_TABLE\n(\n SOME_PK   ASC\n);\nCREATE UNIQUE INDEX index666 ON\nOTHER_TABLE\n(\n OTHER_PK   ASC\n);\n"; 

     Pattern p = Pattern.compile("([^;]*?('.*?')?)*?;\\s*", Pattern.CASE_INSENSITIVE | Pattern.DOTALL | Pattern.MULTILINE); 

     Matcher m = p.matcher(s); 

     while (m.find()) 
     { 
     System.out.println ("--- Statement ---"); 
     System.out.println (m.group()); 
     } 
    } 
} 

la salida será:

--- Statement --- 
CREATE UNIQUE INDEX index555 ON 
SOME_TABLE 
(
    SOME_PK   ASC 
); 

--- Statement --- 
CREATE UNIQUE INDEX index666 ON 
OTHER_TABLE 
(
    OTHER_PK   ASC 
); 
3

Salida las diversas banderas que se pueden pasar a Pattern.compile. Creo que DOTALL es lo que necesitas.

8

Comprobar this

La expresión regular. coincide con cualquier carácter excepto un terminador de línea a menos que se especifique el distintivo dotall

Así que hay que hacer algo como esto

Pattern p = Pattern.compile("your pattern", Pattern.DOTALL); 
5

La bandera DOTALL permite las nuevas líneas de concordancia ., pero si simplemente aplicarlo a su expresión regular existente, que va a terminar haciendo coincidir todo, desde el primer CREATE hasta el último ; de una vez. Si quiere hacer coincidir los enunciados individualmente, tendrá que hacer más. Una opción es usar un cuantificador no expansivo:

Pattern p = Pattern.compile("^CREATE\\b.+?;", 
    Pattern.DOTALL | Pattern.MULTILINE | Pattern.CASE_INSENSITIVE); 

También utilicé la bandera MULTILINE para dejar el partido ^ ancla después de los saltos de línea, y CASE_INSENSITIVE se debe a que SQL - al menos, todos los sabores que he oído de . Tenga en cuenta que las tres banderas tienen formas "en línea" que se pueden utilizar en la expresión regular en sí:

Pattern p = Pattern.compile("(?smi)^CREATE\\b.+?;"); 

(El formulario en línea de DOTALL es s por razones históricas, sino que fue llamado modo "de una sola línea" en Perl, . donde se originó) Otra opción es utilizar una clase de caracteres negada:

Pattern p = Pattern.compile("(?mi)^CREATE\\b[^;]+;"); 

[^;]+ partidos uno o más de cualquier carácter excepto ; --que incluye saltos de línea, por lo que no es necesaria la bandera s.

Hasta ahora, he asumido que cada declaración se inicia en el comienzo de una línea y termina con un punto y coma, como en el ejemplo. No creo que el estándar SQL exija ninguna de esas cosas, pero supongo que sabrá si puede contar con ellas en este caso.Es posible que desee empezar a comparar a un límite de palabra en lugar de un límite de una línea:

Pattern p = Pattern.compile("(?i)\\bCREATE\\b[^;]+;"); 

Por último, si usted está pensando en hacer algo más complicado con expresiones regulares y SQL, no lo hacen. Analizar SQL con expresiones regulares es un juego de tontos, es un ajuste aún peor que HTML y expresiones regulares.

Cuestiones relacionadas