2013-02-04 16 views
7

Questi dati di esempio viene restituito dal servizio WebJava: Regular Expression sfuggire Espressione regolare

200,6, "California, Stati Uniti d'America" ​​

voglio dividere utilizzando split(",") e provato a vedere il risultato usando un codice semplice.

String loc = "200,6,\"California, USA\"";  
String[] s = loc.split(","); 

for(String f : s) 
    System.out.println(f); 

Purtroppo questo è il risultato

200 
6 
"California 
USA" 

Il risultato atteso dovrebbe essere

200 
6 
"California, USA" 

ho provato diverse espressioni regolari e senza fortuna. È possibile sfuggire all'espressione regolare specificata all'interno di ""?

UPDATE 1: Aggiunto C# Codice

UPDATE 2: Rimosso C# Codice

+0

Ti aspetti di vedere più di un articolo quotato sulla stessa linea? – dasblinkenlight

+0

Hmmm. Solo frase/parole all'interno di "" "' –

+0

possibile duplicato di [Parsing input CSV con un RegEx in java] (http://stackoverflow.com/questions/1441556/parsing-csv-input-with-a-regex-in -java) – assylias

risposta

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

Questo è l'espressione regolare che si desidera (per dirla in funzione split avrete bisogno per sfuggire le virgolette nella stringa)

Spiegazione

È necessario trovare tutti i ',' s non tra virgolette .. Questo è necessario lookahead (http://www.regular-expressions.info/lookaround.html) per vedere se la virgola corrispondente corrente è tra virgolette o fuori.

Per fare che usiamo lookahead per garantire in pratica l'abbinamento corrente '' è seguito da un numero pari di '"' caratteri (nel senso che esso si trova citazioni esterne)

Così (?:[^"]|"[^"]*")*$ significa partita solo quando c'è sono i caratteri non di citazione fino alla fine o un paio di citazioni con qualcosa tra di loro

(?=(?:[^"]|"[^"]*")*$) sarà lookahead per la partita di cui sopra

,(?=(?:[^"]|"[^"]*")*$) e, infine, questo corrisponderà all '' con il lookahead sopra

+0

Anche il numero di preventivi non significa necessariamente "" al di fuori delle virgolette "" (supponendo che le virgolette possano essere annidate come parentesi). ad esempio, vedere la frase precedente. –

+0

Consentire '' sdfdsf "sdfsdf" sdfsdf "sdfsdf" sdf "' come token, ma è anche valido CSV? – nhahtdh

0

Se c'è una buona biblioteca lexer/parser per Java, è possibile definire un lexer come il seguente codice di pseudo-lexer:

Delimiter: , 
Item: ([^,"]+) | ("[^,"]+") 
Data: Item Delimiter Data | Item 

Come lexer lavoro è che inizia alla definizione token a livello superiore (in questo caso Data) e tenta di formare token fuori dalla stringa fino a quando non può o fino a quando la stringa è finita. Quindi nel caso della stringa si verifica quanto segue:

  • Desidero rendere Dati su 200,6, "California, USA".
  • È possibile creare dati da un elemento, un delimitatore e dati.
  • Ho guardato - 200 è un oggetto e quindi, è un delimitatore, quindi posso renderlo riconoscibile e andare avanti.
  • Desidero rendere i dati su 6, "California, USA"
  • È possibile creare dati da un elemento, un delimitatore e dati.
  • Ho visto - 6 è un oggetto e quindi, è un delimitatore, quindi posso renderlo chiaro e continuare.
  • Desidero rendere i dati fuori "California, USA"
  • Posso rendere i dati di un elemento, un delimitatore e dati.
  • Ho cercato - "California, USA" è un articolo, ma non vedo Delimitatore dopo, quindi proviamo qualcos'altro.
  • Posso creare dati da un articolo.
  • Ho guardato: "California, USA" è un oggetto, quindi posso renderlo chiaro e continuare.
  • La stringa è vuota. Ho finito. Ecco i tuoi token.

(ho imparato a come lexer funzionano dalla guida di esercitare, un pitone lexer/parser: http://www.dabeaz.com/ply/ply.html)

2

Una soluzione più semplice potrebbe essere quella di utilizzare una libreria esistente, come ad esempio OpenCSV per analizzare i dati. Questo può essere realizzato in due linee con questa libreria:

CSVParser parser = new CSVParser(); 
String [] data = parser.parseLine(inputLine); 

Questo diventerà particolarmente importante se si dispone di valori più complesse CSV a tornare in futuro (valori più righe, o valori con citazioni sfuggiti all'interno di un elemento, ecc) . Se non vuoi aggiungere la dipendenza, puoi sempre usare il loro codice come riferimento (sebbene non sia basato su RegEx)

0

Ciao Prova questa espressione.

public class Test { 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     String loc = "200,6,\"Paris, France\""; 
     String[] str1 =loc.split(",(?=(?:[^\"]|\"[^\"]*\")*$)"); 

     for(String tmp : str1){ 
      System.out.println(tmp); 
     } 

    } 

} 
Problemi correlati