Вы хотите использовать scan
для такого рода вещей.Базовый шаблон будет выглядеть так:
s.scan(/\w+/)
Это даст вам массив всех последовательных последовательностей для символов слова:
>> "@Identifier('VariableA', 'VariableB', 'VariableX', 'VariableZ')".scan(/\w+/)
=> ["Identifier", "VariableA", "VariableB", "VariableX", "VariableZ"]
Вы говорите, что у вас может быть несколько экземпляров вашего шаблонас произвольными вещами, окружающими их.Вы можете справиться с этим с помощью вложенных scan
s:
s.scan(/@(\w+)\(([^)]+?)\)/).map { |m| [ m.first, m.last.scan(/\w+/) ] }
Это даст вам массив массивов, каждый внутренний массив будет иметь часть «Идентификатор» в качестве первого элемента, а часть «Переменная»как массив во втором элементе.Например:
>> s = "pancakes @Identifier('VariableA', 'VariableB', 'VariableX', 'VariableZ') pancakes @Pancakes('one','two','three') eggs"
>> s.scan(/@(\w+)\(([^)]+?)\)/).map { |m| [ m.first, m.last.scan(/\w+/) ] }
=> [["Identifier", ["VariableA", "VariableB", "VariableX", "VariableZ"]], ["Pancakes", ["one", "two", "three"]]]
Если вы можете столкнуться с экранированными кавычками внутри битов "Variable", тогда вам понадобится нечто более сложное.
Некоторые примечания к выражению:
@ # A literal "@".
( # Open a group
\w+ # One more more ("+") word characters ("\w").
) # Close the group.
\( # A literal "(", parentheses are used for group so we escape it.
( # Open a group.
[ # Open a character class.
^) # The "^" at the beginning of a [] means "not", the ")" isn't escaped because it doesn't have any special meaning inside a character class.
] # Close a character class.
+? # One more of the preceding pattern but don't be greedy.
) # Close the group.
\) # A literal ")".
Вам на самом деле не нужно [^)]+?
здесь, просто [^)]+
подойдет, но я использую не жадные формы по привычке, потому что обычно это то, что я имею в виду.Группировка используется для разделения частей @Identifier
и Variable
, чтобы мы могли легко получить желаемый вывод вложенного массива.