2010-08-25 9 views
5

Mam ten ciąg tutaj:Czy regex ignoruje nowe linie i pasuje do całego dużego ciągu?

CREATE UNIQUE INDEX index555 ON 
SOME_TABLE 
(
    SOME_PK   ASC 
); 

Chcę dopasować poprzek wielu linii i mecz SQL (wszystkie z nich, nie będzie wielu w 1 dużym ciągiem) ... coś takiego, jednak Dostaję tylko spotkanie na CREATE UNIQUE INDEX index555 ON

(CREATE\s.+;) 

uwaga: staram się tego dokonać w java, jeśli to ma znaczenie.

Odpowiedz

13

trzeba użyć dotall i flagi MultiLine przy kompilacji wyrażenia regularnego. Oto przykład kodu 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()); 
     } 
    } 
} 

wyjście będzie:

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

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

Sprawdź różne flagi, które można przekazać do Pattern.compile. Myślę, że DOTALL to ten, którego potrzebujesz.

8

Sprawdź this

Wyrażenie regularne. dopasowuje dowolny znak z wyjątkiem linii terminatora, chyba że flaga dotall podano

Więc trzeba zrobić coś takiego

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

DOTALL flaga pozwala na . nowe linie meczu, ale jeśli po prostu zastosować go do istniejącej regex, będzie koniec dopasowywanie wszystkiego od pierwszego CREATE do ostatniego ; za jednym razem. Jeśli chcesz indywidualnie dopasować wyciągi, musisz zrobić więcej. Jedną z opcji jest użycie non-chciwy kwantyfikator:

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

użyłem również flagę MULTILINE pozwolić meczu ^ kotwicy po nowej linii, a CASE_INSENSITIVE ponieważ SQL jest - przynajmniej każdy smak Słyszałem . Zauważ, że wszystkie trzy flagi mają „wbudowane” formy, które można wykorzystać w regex samego:

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

(Formularz inline z DOTALL jest s ze względów historycznych; nazwano tryb „single-Line” w Perl, . gdzie to pochodzi) Inną opcją jest użycie zanegowane klasę postaci:

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

[^;]+ mecze jeden lub więcej charakteru wyjątkiem ; --that zawiera znaki nowej linii, więc flaga s nie jest potrzebne.

Do tej pory zakładałem, że każda instrukcja zaczyna się na początku wiersza i kończy się średnikiem, jak w twoim przykładzie. Nie sądzę, że żadna z tych rzeczy nie jest wymagana przez standard SQL, ale spodziewam się, że wiesz, czy możesz na nich liczyć w tym przypadku.Może chcesz rozpocząć dopasowanie na granicy słowa, a nie linia graniczna:

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

Wreszcie, jeśli myślisz o zrobieniu czegoś bardziej skomplikowanego z regexes i SQL, nie. Parsowanie SQL za pomocą wyrażenia regularnego jest grą głupca - jest to jeszcze gorsze dopasowanie niż HTML i wyrównywanie.

Powiązane problemy