2016-03-14 15 views
6

Sto cercando di abbinare qualsiasi istanza di testo in un elenco delimitato da virgole. Per questo, la seguente espressione regolare funziona alla grande:Elementi corrispondenti in un elenco delimitato da virgole che non sono circondati da virgolette singole o doppie

/[^,]+/g 

(Regex101 demo).

Il problema è che sto ignorando tutte le virgole che sono contenute all'interno di virgolette singole o doppie e non sono sicuro di come estendere il selettore precedente per consentirmi di farlo.

Ecco una stringa di esempio:

abcd, efgh, ij"k,l", mnop, 'q,rs't 

Sono voler né corrispondere i cinque porzioni di testo o partita quattro virgole rilevanti (posso prelevare i dati utilizzando split() invece di match()):

  1. abcd
  2. efgh
  3. ij"k,l"
  4. mnop
  5. 'q,rs't

Oppure:

abcd, efgh, ij"k,l", mnop, 'q,rs't 
    ^ ^ ^ ^

Come posso fare questo?


Tre domande pertinenti esistono, ma nessuno di loro soddisfare sia ' e " in JavaScript:

  1. Regex for splitting a string using space when not surrounded by single or double quotes - soluzione Java, non sembra lavorare in JavaScript.
  2. A regex to match a comma that isn't surrounded by quotes - corrisponde solo su "
  3. Alternative to regex: match all instances not inside quotes - partite Solo su "
+0

@ WiktorStribiżew fallisce quando uno spazio si trova accanto a una virgola tra virgolette (https://regex101.com/r/cW5hM0/2). –

+0

@ WiktorStribiżew che si tratti di qualcosa di diverso dalle virgolette come una corrispondenza diversa, indipendentemente da una virgola: https://regex101.com/r/cW5hM0/4 (notare il carattere 'k' in quello). –

+0

([^,] + ". *" [^,]) + | ([^,]? '. *' [^,]) + | ([^,] +)/G, questo dovrebbe funzionare e acquisire i gruppi che vuoi – SamyQc

risposta

3

Va bene, in modo che i gruppi corrispondenti possono contenere:

  • soli lettere
  • una coppia corrispondente di "
  • Una coppia corrispondente di '

Quindi questo dovrebbe funzionare:

/((?:[^,"']+|"[^"]*"|'[^']*')+)/g 

RegEx101 Demo

Come un bel bonus, si puoi rilasciare virgolette singole all'interno delle virgolette e viceversa. Tuttavia, probabilmente avrai bisogno di una macchina a stati per aggiungere doppie virgolette di escape all'interno di stringhe tra virgolette doppie (ad esempio "aa \" aa ").

Sfortunatamente corrisponde anche allo spazio iniziale - dovrai . tagliare le partite

0

Prova questo in JavaScript

(?:(?:[^,"'\n]*(?:(?:"[^"\n]*")|(?:'[^'\n]*'))[^,"'\n]*)+)|[^,\n]+ 

Demo

gruppo Aggiungi per più leggibile (rimuovere?< nome> per JavaScript)

(?<has_quotes>(?:[^,"'\n]*(?:(?<double_quotes>"[^"\n]*")|(?<single_quotes>'[^'\n]*'))[^,"'\n]*)+)|(?<simple>[^,\n]+) 

Demo

Spiegazione:

(?<double_quotes>"[^"\n]*") partite " Qualsiasi all'interno, ma non "" = (1) (in doppio apice)
(?<single_quotes>'[^'\n]*') partite ' Qualsiasi interno ma non "' = (2) (in singolo apice)
(?:(?<double_quotes>"[^"\n]*")|(?<single_quotes>'[^'\n]*')) partite (1) o (2) = (3)
[^,"'\n]* partite alcun testo, ma non "', = (w)
(?:(?:(?<double_quotes>"[^"\n]*")|(?<single_quotes>'[^'\n]*'))[^,"'\n]*) partite (3) (w)
(?:(?:(?<double_quotes>"[^"\n]*")|(?<single_quotes>'[^'\n]*'))[^,"'\n]*)+ partite ripetono (3) (w) = (3w +)
(?<has_quotes>[^,"'\n]*(?:(?:(?<double_quotes>"[^"\n]*")|(?<single_quotes>'[^'\n]*'))[^,"'\n]*)+) partite (w) (3w +) = (4) (ha virgolette)
012.382.362,392 milapartite altri casi (5) (semplice)
Quindi, in definitiva abbiamo (4) | (5) (ha quote o semplice)

ingresso

abcd,efgh, ijkl 
abcd, efgh, ij"k,l", mnop, 'q,rs't 
'q, rs't 
"'q,rs't, ij"k, l"" 

uscita:

MATCH 1 
simple [0-4] `abcd` 
MATCH 2 
simple [5-9] `efgh` 
MATCH 3 
simple [10-15] ` ijkl` 
MATCH 4 
simple [16-20] `abcd` 
MATCH 5 
simple [21-26] ` efgh` 
MATCH 6 
has_quotes [27-35] ` ij"k,l"` 
double_quotes [30-35] `"k,l"` 
MATCH 7 
simple [36-41] ` mnop` 
MATCH 8 
has_quotes [42-50] ` 'q,rs't` 
single_quotes [43-49] `'q,rs'` 
MATCH 9 
has_quotes [51-59] `'q, rs't` 
single_quotes [51-58] `'q, rs'` 
MATCH 10 
has_quotes [60-74] `"'q,rs't, ij"k` 
double_quotes [60-73] `"'q,rs't, ij"` 
MATCH 11 
has_quotes [75-79] ` l""` 
double_quotes [77-79] `""` 
2

Utilizzando un doppio lookahead per accertare virgola abbinato è citazioni fuori:

/(?=(([^"]*"){2})*[^"]*$)(?=(([^']*'){2})*[^']*$)\s*,\s*/g 
  • (?=(([^"]*"){2})*[^"]*$) afferma che ci sono anche il numero di doppi apici avanti di corrispondenza virgola.
  • (?=(([^']*"){2})*[^']*$) fa la stessa affermazione per citazione singola.

PS: Questo non gestisce casi di quotazioni sbilanciate, nidificate o con caratteri di escape.

RegEx Demo

Problemi correlati