2016-09-24 5 views
1

In Java habe ich eine Zeichenfolge (aus einer CSV-Datei entnommen):Java regex für optional eingeschlossen csv-String liefert unerwartete Ergebnisse

40;"blue-collar";"married";"secondary";"no";1100;"yes";"no";"unknown";29;"may";660 

Meine Klasse CSV_Worker wird es durch die gegebene Trennzeichen aufgeteilt (;) und entfernt die Anführungszeichen, falls erforderlich:

public class CSV_Worker { 

    Pattern pattern = null; 
    int colCount = -1; 

    public CSV_Worker (String delimiter, int colCount) { 
    // (?<=^|;)(?:"([^;]*)"|([^;]*))(?=;|$) 
    this.pattern = Pattern.compile("(?<=^|\\" + delimiter + ")(?:\"([^\\" + delimiter + "]*)\"|([^\\" + delimiter + "]*))(?=\\" + delimiter + "|$)"); 
    this.colCount = colCount; 
    } 

    public String [] split (String line) { 

    String [] result = new String[this.colCount]; 
    Matcher m = pattern.matcher(line); 
    int idx = 0; 
    while (m.find()) { 
     result[idx] = m.group(); 
     idx++; 
    } 
    return result; 
    } 
} 

Warum CSV_Worker.split(myString) Rückkehr

40 
"blue-collar" 
"married" 
... 

statt

40 
blue-collar 
married 
... 

?

bearbeiten

Dank der Lösung @Fabian andere regexp war:

(?<=^|\|)"?((?<!")[^\|]*(?!")|(?<=")[^"]*(?="))"?(?=\||$) 

enter image description here

Debuggex Demo

+0

Versuchen Sie 'String [] result = line.replaceAll ("^\ "| \" $ "," ") .split (" \ "?; \"? ");'. – saka1029

+0

grundsätzlich eine gute Idee, aber die Anführungszeichen sind nicht unabhängig voneinander. Die Zeichenfolge enthält möglicherweise nur ein Element mit einem führenden/nachfolgenden Anführungszeichen, das im Ergebnis enthalten sein muss. – Benvorth

+2

Versuchen Sie nicht, CSV-Daten mit Regex zu analysieren. Verwenden Sie einen CSV-Parser. Dafür sind sie da. – Andreas

Antwort

2

Mit m.group() man das ganze Spiel erhalten (dh Gruppe 0) nicht nur der Inhalt eines Captures Gruppen. Dazu gehören die Zitate aus Ihrer nicht erfassten Gruppe. Außerdem verwenden Sie verschiedene Erfassungsgruppen für den Fall, in dem es Anführungszeichen gibt und keine Anführungszeichen vorhanden sind. Sie müssen daher die Matcher wie folgt verwenden:

String g1 = m.group(1); 
result[idx] = (g1 == null ? m.group(2) : g1); 

Sie auch nur eine einzige Erfassungsgruppe unter Verwendung lookarounds

Pattern pattern = Pattern.compile("(?<=^|\\" + delimiter + ")\"?((?<!\")[^\\" + delimiter + "]*(?!\")|(?<=\")[^\"]*(?=\"))\"?(?=\\" + delimiter + "|$)"); 

die

result[idx] = m.group(1); 
verwenden können Sie nutzen könnten

in der Split-Methode statt.

+0

smart, danke dafür. Ich habe die zweite Lösung verwendet, da sie schneller ist. – Benvorth

+0

BTW: Ihre Lösung wird perfekt, wenn der positive Lookaround (2. Teil in oder) durch '(? <= \") [^ "] * (? = \") 'Ersetzt wird. Er passt jetzt zu Elementen wie ... "afw; e22"; ... auch – Benvorth

Verwandte Themen