7 Stimmen

Regulärer Ausdruck zur Extraktion von Label-Wert-Paaren in Java

Ich habe eine Datei, die mehrere Zeilen ähnlich wie diese enthält:

Name: Peter
Address: St. Serrano número 12, España
Country: Spain

Und ich muss die Adresse mit Hilfe eines regulären Ausdrucks extrahieren, wobei zu berücksichtigen ist, dass sie Punkte, Sonderzeichen (ñ, ç), áéíóú... enthalten kann.

Der aktuelle Code funktioniert, sieht aber ziemlich hässlich aus:.

Pattern p = Pattern.compile("^(.+?)Address: ([a-zA-Z0-9ñÑçÇáéíóú., ]+)(.+?)$",
                            Pattern.MULTILINE | Pattern.DOTALL);
Matcher m = p.matcher(content);
if (m.matches()) { ... }

Bearbeiten: Das Adressfeld könnte auch in mehrere Zeilen aufgeteilt werden

Name: Peter
Address: St. Serrano número 12,   
Madrid
España
Country: Spain

Edit: Ich kann weder ein Properties-Objekt noch einen YAML-Parser verwenden, da die Datei auch andere Informationen enthält.

6voto

ʞɔıu Punkte 44966

Ich kenne mich mit den Regex-Objekten von Java nicht so gut aus, aber so etwas wie dieses Muster wird es tun:

^Address:\s*((?:(?!^\w+:).)+)$

vorausgesetzt, die Modi Multiline und Dotall sind aktiviert.

Dies entspricht jeder Zeile, die mit Adresse beginnt, gefolgt von allem bis zu einem Zeilenumbruch und einem einzelnen Wort, gefolgt von einem Doppelpunkt.

Wenn Sie wissen, dass das nächste Feld "Land" sein muss, können Sie dies ein wenig vereinfachen:

^Address:\s*((?:(?!^Country:).)+)$

Der Trick liegt in der Vorausschau-Behauptung in der Wiederholungsgruppe. '(?!Land:).' passt auf alles außer dem Anfang der Zeichenkette 'Land:', also setzen wir sie einfach in nicht-erfassende Klammern (?:...) und quantifizieren sie mit +, dann gruppieren wir das Ganze in normale erfassende Klammern.

3voto

Cem Catikkas Punkte 7133

Sie sollten sich vielleicht mit folgenden Themen befassen Properties Klasse anstelle von regex. Sie bietet Ihnen Möglichkeiten, einfache Text- oder XML-Dateien zu verwalten, um Schlüssel-Wert-Paare darzustellen.

Sie können also Ihre Beispieldatei einlesen und dann die Werte nach dem Laden in eine Properties Objekt:

Properties properties = new Properties();
properties.load(/* InputStream of your file */);

Assert.assertEquals("Peter", properties.getProperty("Name"));
Assert.assertEquals("St. Serrano número 12, España", properties.getProperty("Address"));
Assert.assertEquals("Spain", properties.getProperty("Country"));

3voto

Alan Moore Punkte 70949

Unter der Annahme, dass "content" eine Zeichenkette ist, die den Inhalt der Datei enthält, besteht Ihr Hauptproblem darin, dass Sie mit matches() wo Sie Folgendes verwenden sollten find() .

Pattern p = Pattern.compile("^Address:\\s*(.*)$", Pattern.MULTILINE);
Matcher m = p.matcher(content);
if ( m.find() )
{
  ...
}

In anderen Antworten scheint es einige Verwirrung über die Modi MULTLINE und DOTALL zu geben. Mit MULTILINE kann die ^ y $ Anker entsprechen dem Anfang bzw. dem Ende einer logischen Zeile. DOTALL lässt den Punkt (Punkt, Punkt, Punkt, was auch immer) mit Zeilentrennzeichen wie \n (Zeilenumbruch) und \r (Wagenrücklauf). Diese Regex debe den Modus MULTILINE verwenden und darf nicht den DOTALL-Modus verwenden.

1voto

Dave Ray Punkte 38948

Ich will ja kein Spielverderber sein, aber müssen Sie eine Regex verwenden? Warum ersparen Sie sich (oder anderen) nicht die Kopfschmerzen und tun es:

String line = reader.readLine();
while(line != null)
{
    line = line.trim();
    if(line.startsWith("Address: "))
    {
        return line.substr("Address: ".length()).trim();
    }
    line = reader.readLine();
}
return null;

Natürlich kann man das auch ein bisschen parametrisieren und in eine Methode packen.

Ansonsten würde ich die Vorschläge von Properties oder JYaml unterstützen.

0voto

cnu Punkte 33869

Ich bin kein Java-Kenner, aber würde nicht ein "Address: (.*)$" arbeiten?

Bearbeiten: Ohne die Option Pattern.MULTILINE | Pattern.DOTALL sollte es nur in dieser Zeile passen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X