2013-08-24 7 views

risposta

10

Per affrontare parentesi nidificate, è possibile utilizzare:

txt = "a,s(d,f(4,5)),g,h" 
pattern = Regexp.new('((?:[^,(]+|(\((?>[^()]+|\g<-1>)*\)))+)') 
puts txt.scan(pattern).map &:first 

dettagli del modello:

(      # first capturing group 
    (?:     # open a non capturing group 
     [^,(]+   # all characters except , and (
     |     # or 
     (    # open the second capturing group 
      \(   # (
      (?>   # open an atomic group 
       [^()]+ # all characters except parenthesis 
       |   # OR 
       \g<-1> # the last capturing group (you can also write \g<2>) 
      )*   # close the atomic group 
      \)   #) 
     )    # close the second capturing group 
    )+     # close the non-capturing group and repeat it 
)      # close the first capturing group 

Il secondo gruppo di cattura descrivono la parentesi annidata che può contenere caratteri che non sono parentesi o la cattura gr stesso. È un modello ricorsivo.

All'interno del modello, è possibile fare riferimento ad un gruppo di cattura con il suo numero (\g<2> per il secondo gruppo di cattura), o con la sua posizione relativa (\g<-1> la prima a sinistra dalla posizione corrente nel pattern) (o con il suo nome se si utilizzano gruppi di acquisizione denominati)

Avviso: è possibile consentire una singola parentesi se si aggiunge |[()] prima della fine del gruppo non di acquisizione. Quindi a,b(,c ti darà ['a', 'b(', 'c']

+0

'txt.scan (pattern) .map &: first' ha risolto il problema. @casimir davvero non posso raddoppiare-votare la tua risposta, grazie! – Naveed

+0

puoi spiegare questa espressione regolare? è fuori di testa :) – Naveed

+1

Ero curioso di -1 in regexp. puoi spiegare anche questa parte? <-1> ' – Naveed

2

Supponendo che tra parentesi non sono annidate:

"a,s(d,f),g,h" 
.scan(/(?:\([^()]*\)|[^,])+/) 
# => ["a", "s(d,f)", "g", "h"] 
+0

grazie per le modifiche e la risposta eccezionale! un problema però, questo non soddisfa le parentesi nidificate '" a, s (d, f (4,5)), g, h ".scan/(?: \ ([^()] * \) | [^ ,]) +/'=>' ["a", "s (d", "f (4,5))", "g", "h"] " – Naveed

+0

" a, s (d, f (4 , 5)), g, h "dovrebbe entrare in ['a', 's (d, f (4,5)', 'g', 'h'] – Naveed

+3

Non è un problema. Ho scritto nella risposta: il fatto è che il tuo esempio non ha specificato completamente i casi annidati e ho assunto ciò che non volevi. – sawa

Problemi correlati