2009-06-07 15 views
1

[EDITED - Tut mir wirklich leid, der Code, den ich zitiert habe, war falsch - habe die untenstehende Nachricht geändert, um dies widerzuspiegeln. Entschuldigung! Vielen Dank für Ihre Geduld.]Java - Wie man Regex Muster mit einfachen Anführungszeichen?

Ich bin neu in reguläre Ausdrücke und möchte ein Muster in Java (im Anschluss an diese Lösung - Java string - get everything between (but not including) two regular expressions?) entsprechen.

Die Zeichenfolge wird [EDITED]:

<row><column name='_id'>1</column></row><row><column name='text'>Header\n\n\ntext</column></row><row><column name='pwd'>password</column></row> 

Und ich will nur zurück, was zwischen dem tags = 'text' Spaltenname ist, so:

Header\n\n\ntext 

Ich habe der Code unten [EDITED], aber es stimmt nicht überein. Irgendwelche Ideen, wie ich das Muster ändern muss?

Danke!

package test; 

import java.util.regex.Matcher; 
import java.util.regex.Pattern; 

public class Regex { 

    public static void main(String[] args) { 
     Pattern p = Pattern.compile(
       "<row><column name='text'>(.*)</column></row>", 
       Pattern.DOTALL 
      ); 
     Matcher matcher = p.matcher(
       "<row><column name='_id'>1</column></row><row><column name='text'>Header\n\n\ntext</column></row><row><column name='pwd'>password</column></row>" 
      ); 
     if(matcher.matches()){ 
       System.out.println(matcher.group(1)); 
     } 
    } 
} 

Antwort

4

Der (nicht editierte) Code, den Sie gepostet haben, funktioniert gut für mich ... er passt und gibt die Nachricht aus, die Sie erwarten.

Der bearbeitete Code funktioniert nicht, aber wenn Sie die Regex ändern sich sehr leicht so aussehen:

Pattern p = Pattern.compile(
      ".*<row><column name='text'>(.*)</column></row>.*", 
      Pattern.DOTALL 
     ); 

Sie ein Spiel erhalten:

Header 


text</column></row><row><column name='pwd'>password 

, die wahrscheinlich nicht das, was Sie tatsächlich will aber, so müssen Sie die Regex weiter verfeinern. Die Verwendung von regulären Ausdrücken zum Behandeln von XML/HTML-Parsing ist im Allgemeinen kein guter Ansatz. Yishais Vorschlag, einen XML-Parser zu verwenden, ist ein besserer Weg, um es zu tun, sonst werden Sie höchstwahrscheinlich mit einem enorm komplizierten und unflexiblen regulären Ausdruck enden.

+0

Vielen Dank! Und danke für den Hinweis - ich schaue mir einen XML-Parser an. –

1

Versuchen (.*?) statt nur (.*) entsprechen.

(.*) ist eine gierige Suche, die alles danach abgleichen wird.

(.*?) stoppt beim ersten Auftreten von "</column></row>".

Bearbeiten: Dies sollte nicht wirklich Ihr Beispiel beeinflussen, aber wenn Sie eine andere "</column></row>" in der Zeichenfolge haben, dann wird Ihr Muster nicht wie erwartet übereinstimmen.

3

Vielleicht, was Sie wirklich wollen, bekommen dies ist:

public static void main(String[] args) { 
    Pattern p = Pattern.compile(
      "<row><column name='(.*?)'>(.*?)</column></row>", 
      Pattern.DOTALL 
     ); 

    Matcher matcher = p.matcher(
      "<row><column name='text'>Header\n\n\ntext</column></row>" 
     ); 

    if(matcher.matches()){ 
      System.out.println(matcher.group(2)); 
    } 
} 

Weil Ihr reales Beispiel etwas im name = Wert haben könnte (zumindest die viel mehr der realen Welt scheint).

Wenn das viel mehr nicht-trivial wird, möchten Sie vielleicht dies als SAX-Parser betrachten (das in das JDK 1.5+ integriert ist, so dass es nicht unbedingt ein Bibliotheksabhängigkeitsproblem ist). . Regex ist ein besserer Weg, um XML zu parsen, wenn Sie sich nicht wirklich um die Dokumentenstruktur kümmern und nur etwas Triviales daraus aussaugen wollen. Wenn Sie jedoch mit Attributen beginnen und sich darum kümmern, was sie in XML sind, wird das Rad neu erfunden, wenn Sie die Regex-Route fortsetzen.

0

Ihr Problem hat nichts mit den Anführungszeichen zu tun. Sie müssen nur auf einen nicht-gierigen Quantor wechseln (wie andere vorgeschlagen haben) und verwenden Sie die find() Methode statt matches():

public static void main(String[] args) 
{ 
    Pattern p = Pattern.compile(
     "<row><column name='text'>(.*?)</column></row>", 
     Pattern.DOTALL 
); 

    Matcher matcher = p.matcher(
     "<row><column name='_id'>1</column></row>" + 
     "<row><column name='text'>Header\n\n\ntext</column></row>" + 
     "<row><column name='pwd'>password</column></row>" 
); 

    if(matcher.find()) { 
     System.out.println(matcher.group(1)); 
    } 
} 

matches() kehrt true nur dann, wenn der Regex von Anfang an der Zielzeichenfolge entspricht zu das Ende. Wenn Sie weniger als die gesamte Zeichenfolge abgleichen möchten, müssen Sie find() verwenden.

Verwandte Themen