Разбить строку в Ruby, игнорируя содержимое скобок? - PullRequest
7 голосов
/ 06 января 2010

Мне нужно разбить строку на список частей в Ruby, но мне нужно игнорировать вещи внутри параментезов. Например:

A +4, B +6, C (hello, goodbye) +5, D +3

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

[0]A +4
[1]B +6
[2]C (hello, goodbye) +5
[3]D +3

Но я не могу просто разделить запятыми, потому что это разделит содержимое скобок. Есть ли способ разбить материал, не разбирая запятые в фигурных скобках во что-то еще?

Спасибо.

Ответы [ 2 ]

13 голосов
/ 06 января 2010

Попробуйте это:

s = 'A +4, B +6, C (hello, goodbye) +5, D +3'
tokens = s.scan(/(?:\(.*?\)|[^,])+/)
tokens.each {|t| puts t.strip}

Выход:

A +4
B +6
C (hello, goodbye) +5
D +3

Краткое объяснение:

(?:        # open non-capturing group 1
  \(       #   match '('
  .*?      #   reluctatly match zero or more character other than line breaks
  \)       #   match ')'
  |        #   OR
  [^,]     #   match something other than a comma
)+         # close non-capturing group 1 and repeat it one or more times

Другим вариантом является разделение на запятую, за которой следуют некоторые пробелы, только если первая круглая скобка, которая видна при взгляде вперед, является открывающей круглой скобкой (или вообще без скобок: т.е. конец строки):

s = 'A +4, B +6, C (hello, goodbye) +5, D +3'
tokens = s.split(/,\s*(?=[^()]*(?:\(|$))/)
tokens.each {|t| puts t}

выдаст тот же результат, но я считаю, что метод очистки scan

5 голосов
/ 06 января 2010
string = "A +4, B +6, C (hello, goodbye) +5, D +3"
string.split(/ *, *(?=[^\)]*?(?:\(|$))/)
# => ["A +4", "B +6", "C (hello, goodbye) +5", "D +3"]

Как работает это регулярное выражение:

/
   *, *        # find comma, ignoring leading and trailing spaces.
  (?=          # (Pattern in here is matched against but is not returned as part of the match.)
    [^\)]*?    #   optionally, find a sequence of zero or more characters that are not ')'
    (?:        #   <non-capturing parentheses group>
      \(       #     left paren ')'
      |        #     - OR -
      $        #     (end of string)
    )
  )
/
...