2010-08-25 9 views
5

Ho questa stringa qui:Le espressioni regolari ignorano le nuove righe e corrispondono semplicemente a un'intera stringa di grandi dimensioni?

CREATE UNIQUE INDEX index555 ON 
SOME_TABLE 
(
    SOME_PK   ASC 
); 

voglio corrispondere attraverso le più righe e abbinare le istruzioni SQL (tutti loro, ci saranno molti in 1 stringa di grandi dimensioni) ... qualcosa di simile, però sto ottenendo soltanto una partita in CREATE UNIQUE INDEX index555 ON

(CREATE\s.+;) 

nota: sto cercando di ottenere questo risultato in java se è importante.

risposta

13

È necessario utilizzare DOTALL e bandiere MULTILINEA quando si compila un'espressione regolare. Ecco un esempio di codice 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()); 
     } 
    } 
} 

l'uscita sarà:

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

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

Controllare le varie bandiere che è possibile passare a Pattern.compile. Penso che DOTALL sia quello di cui hai bisogno.

3

Si desidera utilizzare il flag Pattern.DOTALL in modo che corrisponda attraverso le linee.

8

check this

L'espressione regolare. qualsiasi carattere ad eccezione di una terminazione di linea se non viene specificato il flag DOTALL

quindi è necessario fare qualcosa di simile

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

La bandiera DOTALL lascia i . partita ritorni a capo, ma se semplicemente applicare al vostro regex esistente, vi ritroverete fino ad abbinare tutto, dal primo CREATE all'ultimo ; in una volta. Se vuoi abbinare le dichiarazioni individualmente, dovrai fare di più. Una possibilità è quella di utilizzare un quantificatore non avido:

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

ho usato anche la bandiera MULTILINE di lasciare che il match ^ ancoraggio dopo a capo, e CASE_INSENSITIVE perché SQL è - almeno, ogni sapore ho sentito di . Da notare che tutte e tre le bandiere hanno forme "in linea" che è possibile utilizzare nella regex stesso:

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

(La forma in linea di DOTALL è s per ragioni storiche, è stato chiamato in modalità "single-line" in Perl, . dove ha avuto origine) Un'altra opzione è quella di utilizzare una classe di caratteri negata:

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

[^;]+ corrisponde a uno o più di qualsiasi carattere tranne ; --that include nuove linee, per cui non è necessaria la bandiera s.

Finora, ho assunto che ogni istruzione inizi all'inizio di una riga e termini con un punto e virgola, come nel tuo esempio. Non penso che nessuna di queste cose sia richiesta dallo standard SQL, ma prevedo che saprai se puoi contare su di esse in questa istanza.Si potrebbe desiderare di iniziare corrispondenti ad un confine di parola, invece di una linea di confine:

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

Infine, se stai pensando di fare qualcosa di più complicato con le regex e SQL, no. L'analisi di SQL con regex è un gioco da pazzi: è un adattamento ancora peggiore rispetto all'HTML e alle regex.

Problemi correlati