Frage

Ich weiß, ich habe jetzt zwei Probleme. Aber ich habe Spaß!

Ich begann mit diese Beratung nicht versuchen und geteilt, sondern auf entsprechen, was ein akzeptabler Bereich, und diesen Ausdruck von dort erweitert.

final Pattern pattern = Pattern.compile("\"([^\"]*)\"|(?<=,|^)([^,]*)(?=,|$)");

Der Ausdruck sieht wie folgt aus, ohne die lästigen entgangen Zitate:

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

Das funktioniert gut für mich - entweder es passt auf „zwei Zitate und was auch immer zwischen ihnen“, oder „etwas zwischen dem Anfang der Zeile oder ein Komma und das Ende der Zeile oder ein Komma“. Iterieren durch die Spiele bekommt mir alle Felder, auch wenn sie leer sind. Zum Beispiel

the quick, "brown, fox jumps", over, "the",,"lazy dog"

gliedert sich in

the quick
"brown, fox jumps"
over
"the"

"lazy dog"

Great! Jetzt mag ich die Zitate fallen zu lassen, so dass ich hinzugefügt, um den Look-Ahead und Lookbehind nicht-einfangenden Gruppen wie ich für die Kommas tat.

final Pattern pattern = Pattern.compile("(?<=\")([^\"]*)(?=\")|(?<=,|^)([^,]*)(?=,|$)");

wieder der Ausdruck ist:

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

Statt des gewünschten Ergebnisses

the quick
brown, fox jumps
over
the

lazy dog

ich diesen Zusammenbruch jetzt bekommen:

the quick
"brown
 fox jumps"
,over,
"the"
,,
"lazy dog"

Was bin ich fehlt?

War es hilfreich?

Lösung

Operator Vorrang. Grundsätzlich gibt es keine. Es ist alles links nach rechts. So ist die oder (|) bewirbt sich mit dem Schlusskurs Look-Ahead und das Komma Look-Ahead

Versuchen:

(?:(?<=")([^"]*)(?="))|(?<=,|^)([^,]*)(?=,|$)

Andere Tipps

(?:^|,)\s*(?:(?:(?=")"([^"].*?)")|(?:(?!")(.*?)))(?=,|$)

Dies sollte das tun, was Sie wollen.

Erklärung:

(?:^|,)\s*

Das Muster sollte mit einem oder Anfang Zeichenfolge beginnen. Auch ignoriert alle Leerzeichen am Anfang.

Die Look-Ahead und sehen, ob der Rest mit einem Zitat beginnt

(?:(?=")"([^"].*?)")

Ist dies der Fall, dann passen nicht-gierig bis zum nächsten Angebot.

(?:(?!")(.*?))

Wenn es nicht mit einem Zitat beginnt, dann nicht gierig bis zum nächsten Komma oder Ende der Zeichenkette entspricht.

(?=,|$)

Das Muster sollte mit einem Komma oder Ende der Zeichenkette beenden.

Als ich begann zu verstehen, was ich falsch gemacht hatte, begann ich auch zu verstehen, wie verworren die lookarounds dies machten. Ich erkannte schließlich, dass ich nicht den ganzen Text abgestimmt wollte, habe ich bestimmte Gruppen in der es wollte. Ich landete außer der Verwendung von etwas sehr ähnlich zu meiner ursprünglichen RegEx, dass ich einen Look-Ahead auf dem Schluss Komma nicht getan hat, was meiner Meinung nach sollte ein wenig effizienter sein. Hier ist mein letzter Code.

package regex.parser;

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

public class CSVParser {

    /*
     * This Pattern will match on either quoted text or text between commas, including
     * whitespace, and accounting for beginning and end of line.
     */
    private final Pattern csvPattern = Pattern.compile("\"([^\"]*)\"|(?<=,|^)([^,]*)(?:,|$)");  
    private ArrayList<String> allMatches = null;    
    private Matcher matcher = null;
    private String match = null;
    private int size;

    public CSVParser() {        
        allMatches = new ArrayList<String>();
        matcher = null;
        match = null;
    }

    public String[] parse(String csvLine) {
        matcher = csvPattern.matcher(csvLine);
        allMatches.clear();
        String match;
        while (matcher.find()) {
            match = matcher.group(1);
            if (match!=null) {
                allMatches.add(match);
            }
            else {
                allMatches.add(matcher.group(2));
            }
        }

        size = allMatches.size();       
        if (size > 0) {
            return allMatches.toArray(new String[size]);
        }
        else {
            return new String[0];
        }           
    }   

    public static void main(String[] args) {        
        String lineinput = "the quick,\"brown, fox jumps\",over,\"the\",,\"lazy dog\"";

        CSVParser myCSV = new CSVParser();
        System.out.println("Testing CSVParser with: \n " + lineinput);
        for (String s : myCSV.parse(lineinput)) {
            System.out.println(s);
        }
    }

}

Ich weiß, das ist nicht das, was der OP will, aber für andere Leser, eine der String.replace Methoden verwendet werden könnten, die Zitate von jedem Element im Ergebnisfeld des OPs aktuellen Regex abzustreifen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top