2009-05-10 7 views
5


Ich frage mich, wenn jemand mir helfen herauszufinden, könnte, wie eine Zeichenfolge zu analysieren, mit dem folgende Format:Parsing ein String Escape-Zeichen enthalten, unter Verwendung von Java

;field1-field2-fieldN;field1-field2-fieldN; 

Jeder Datensatz durch begrenzt ist ‚;‘ und jedes Feld innerhalb eines Datensatzes wird durch '-' begrenzt. Die Komplikation besteht darin, dass die einzelnen Felder maskierte Trennzeichen wie "\" enthalten können. oder "-". Dies führt dazu, dass mein einfacher Parsing-Code fehlschlägt. Also versuche ich, Regex-Ausdrücke zu finden, die mit den Trennzeichen übereinstimmen, aber nicht mit den Escape-Trennzeichen übereinstimmen. Mein Regex-Wissen ist nicht so toll, aber ich habe erwartet, dass es eine Möglichkeit gibt, "([^ \;])" und "([;])" zu kombinieren, um das zu bekommen, was ich benötige.

public static List<ParsedRecord> parse(String data) { 
    List<ParsedRecord> parsedRecords = new List<ParsedRecord>(); 
    String[] records = data.split(";"); 
    for (String record : records) { 
     String[] fields = data.split("-"); 
     parsedRecords.add(new parsedRecord(fields)); 
    } 
    return parsedRecords; 
} 

Vielen Dank im Voraus.

Antwort

7

Sie vielleicht Ihren regulären Ausdruck mit Split so benutzten verfeinern konnte:

split("[^\\];") 

So teilen Sie auf alles, was ein „;“. aber nicht, wenn vorher ein "\" vorhanden ist. Und das gleiche für die Striche:

split("[^\\]-") 
+0

Vielen Dank! Ich habe eine Kombination aus deiner Antwort und Jon benutzt, um den Parser zum Laufen zu bringen. Sehr geschätzt! –

+2

Das ist nicht ganz richtig ... die oben definierte Regex hat das Zeichen vor dem Trennzeichen, das ebenfalls entfernt werden soll. So "Hallo, Welt" wird [Hölle, Welt]. Der bessere Weg ist, den negativen Blick hinter Mechanismus in Regex zu verwenden: http://stackoverflow.com/questions/820172/how-to-split-a-comma-separated-string-while-ignoring-escaped-commas – Alvin

7

Sie sind wahrscheinlich am besten sein, aus der URL-Kodierung und die Spaltung in einem Durchgang zu tun. Ich weiß, dass es sich falsch anfühlt, wenn man die zwei getrennten Teile der Funktionalität trennt, aber es vermeidet einige unbeholfene Eckenfälle (stellen Sie sich beispielsweise "foo \; bar" vor, wobei das; einem Backslash folgt, aber immer noch ein Trennzeichen ist).

Hier ist ein extrem simplen Code die Analyse zu tun - es wird davon ausgegangen, dass jeder Backslash im Grunde bedeutet, „das nächste Zeichen als einfacher Eingang behandeln“, aber das ist alles.

import java.util.*; 

public class Test 
{ 
    public static void main(String[] args) 
    { 
     List<String> parsed = parse(args[0]); 
     for (String x : parsed) 
     { 
      System.out.println(x); 
     } 
    } 

    public static List<String> parse(String text) 
    { 
     List<String> ret = new ArrayList<String>(); 
     StringBuilder current = new StringBuilder(); 
     boolean escaping = false; 

     for (int i=0; i < text.length(); i++) 
     { 
      char c = text.charAt(i); 
      if (escaping) 
      { 
       current.append(c); 
       escaping = false; 
      } 
      else 
      { 
       if (c == '\\') 
       { 
        escaping = true; 
       } 
       else if (c == ';') 
       { 
        ret.add(current.toString()); 
        current = new StringBuilder(); 
       } 
       else 
       { 
        current.append(c); 
       } 
      } 
     } 
     if (escaping) 
     { 
      throw new IllegalArgumentException("Ended in escape sequence"); 
     } 
     ret.add(current.toString()); 
     return ret; 
    } 
} 

(Beachten Sie, dass dies nicht das Geschäft macht jeden Datensatz in mehrere Felder zu spalten, aber Sie würden brauchen nur zu ändern, was Sie tun mit ‚;‘ und reagieren auch auf ‚-‘ - das Prinzip ist das gleiche)