2015-07-01 9 views
5

Ho letto questa stringa da file:Come dividere la stringa con l'espressione regolare di java con lo sguardo dietro?

abc | abc (abc \ | abc) | def

voglio ottenere gamma inludes 3 articoli:

  1. abc
  2. abc (abc \ | ABC)
  3. def

Come scrivere un'espressione regolare in modo corretto? line.split("(?!<=\\)\\|") non funziona.

+0

Qual è la tua condizione di divisione? È '|' che è all'interno di parentesi, o '|' che non ha '' \ '' prima di esso? Inoltre, la tua stringa può essere "abc \ | abc | (ab | ab) '? O anche 'ab \\ | ab \ | ab'? Se sì, come vorresti dividerlo? – Pshemo

+0

sembra che tu debba solo dividere per | carattere. Se questo è ciò che vuoi, puoi semplicemente usare String [] splitedArray = str.split ("\\ |"); –

+0

@RamanShrivastava Non è così semplice. Anche OP si sta già dividendo in '\\ |'. – Pshemo

risposta

2

Codice:

public class __QuickTester { 

    public static void main (String [] args) { 

     String test = "abc|abc (abc\\|abc)|def|banana\\|apple|orange"; 

     // \\\\ becomes \\ <-- String 
     // \\ becomes \ <-- In Regex 
     String[] result = test.split("(?<!\\\\)\\|"); 

     for(String part : result) { 
      System.out.println(part); 
     } 
    } 
} 

uscita:

abc 
abc (abc\|abc) 
def 
banana\|apple 
orange 


Nota: È necessario \\\\ (4 backslash) per ottenere \\ (2 backslash) come String, e poi \\ (2 backslash) diventa un singolo \ in Regex.

+0

Ma la stringa può contenere "abc | abc", aggiorno il mio post – mystdeim

+0

@mystdeim Senza spazi ora e funziona! Penso che sia corretto ora. :) – Gosu

0

provare questo regex: ([\w()]|(\\|))+

0

problema principale nel vostro approccio è che \ è speciale in regex, ma anche in Stringa. Quindi, per creare \ letterale hai bisogno di fuggire due volte:

  • in regex \\
  • in Stringa "\\\\".

così si avrebbe bisogno di scrivere come split("(?<!\\\\)\\|")

Ma ci sono anche i possibili problemi con questo approccio dal frazionamento su | che è semplice preceduta da \ può essere soggetto a errori. Poiché stai utilizzando \ come carattere speciale per creare letterale \, probabilmente devi scriverlo come \\, ad esempio per creare c:\foo\bar\ probabilmente devi scriverlo nel tuo testo come c:\\foo\\bar\\.

Quindi, in questo caso, permette di dire che si desidera dividere il testo come

abc|foo\|c:\\bar\\|cde 

Presumo che si desidera dividere solo in questo pone

abc|foo\|c:\\bar\\|cde 
^   ^

perché

  • in abc|foo pipe | non ha \ prima di esso,
  • in bar\\|cde nonostante tubo avendo \ prima, sappiamo che questo \ non è stato utilizzato per sfuggire |, ma per generare testo che rappresenta \ letterale (così generalmente | che hanno non o addirittura il numero di caratteri \ sono OK per dividere il).

Ma split(onEachPipeWhichHaveBackslashBeforeIt) come split("(?<!\\\\)\\|") non si dividerà tra bar\\|cde perché c'è \ prima | che impedirà tale divisione.

Per risolvere questo problema, è possibile verificare se il numero di | è un numero dispari prima di |, ma è difficile farlo in Java poiché il look-behind deve avere una larghezza limitata.

La soluzione possibile è split("(?<!(?<!\\\\)((\\\\){2}){0,1000}\\\\)\\|") e si suppone che la stringa non contenga mai più di 1000 caratteri \ continui, ma sembra eccessivo.

La soluzione migliore per IMO è la ricerca di stringhe che si desidera trovare, una terza di cercare le stringhe su cui si desidera dividere. E le stringhe che si desidera trovare sono

  • tutti i personaggi tranne |
  • tutti i caratteri che sono preceduti da \ (tra cui | dal \ si limiterà a sfuggire).

Quindi la nostra espressione regolare potrebbe apparire come (\\\\.|[^|])+ (ho messo \\\\. all'avvio per prevenire [^|] consumare \ che sarà utilizzato per sfuggire altri personaggi).

Esempio:

Pattern p = Pattern.compile("(\\\\.|[^|])+"); 
Matcher m = p.matcher(text); 
while (m.find()){ 
    System.out.println(m.group()); 
} 

uscita:

abc 
foo\|c:\\bar\\ 
cde 
Problemi correlati