2013-08-24 4 views
6

Я хочу, чтобы разбить строку запятой:Как разбить строку запятыми, за исключением скобок, используя регулярное выражение?

"a,s".split ',' # => ['a', 's'] 

Я не хочу, чтобы разделить подстроку, если она обернута скобкой:

"a,s(d,f),g,h" 

должен давать:

['a', 's(d,f)', 'g', 'h'] 

Любое предложение?

ответ

10

Чтобы справиться с вложенной скобкой, вы можете использовать:

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

шаблонов детали:

(      # 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 

Вторая группа записи описывают вложенная скобка, которая может содержать символы, которые не являются скобками или захватом gr сам. Это рекурсивный образец.

Внутри шаблона, вы можете обратиться к улавливающей группе с его номером (\g<2> для второго захвата группы) или с его относительным положением (\g<-1> первого на слева от текущей позиции в шаблоне) (или с его имя, если вы используете названные группы захвата)

Примечание: вы можете разрешить одиночную скобку, если вы добавите |[()] до конца группы, не участвующей в захвате. Затем a,b(,c даст вам ['a', 'b(', 'c']

+0

'txt.scan (pattern) .map &: first' решил проблему. @casimir действительно я не могу удвоить ваш голос, спасибо! – Naveed

+0

Вы можете объяснить это регулярное выражение? его из моей головы :) – Naveed

+1

Мне было интересно, -1 в regexp. не могли бы вы также объяснить эту часть '<-1>' – Naveed

2

Предполагая, что круглые скобки не являются вложенными:

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

спасибо за изменения и удивительный ответ! один вопрос, однако, это не будет содержать вложенные круглые скобки '' 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 "должны ломаться в ['a', 's (d, f (4,5)', 'g', 'h'] – Naveed

+3

Это не проблема. Я написал в ответ. Дело в том, что ваш пример не полностью определил вложенные случаи, и я предположил, чего вы не хотели. – sawa

Смежные вопросы