Как получить неопределенное количество захватов в регулярном выражении?
Я делаю простой язык на основе стека, который использует команды для управления стеком. Когда я нахожу команду в источнике, я использую это регулярное выражение, чтобы отделить фактическое имя команды, такое как сумма, и аргументы команды. Аргументы заключены в треугольные скобки и разделены запятыми.
Вот регулярное выражение, которое я сейчас использую:
(?<command>[^<>\s]+)(\<(?<args>(\d+)+(?>,\s*\d+)*)\>)?
Теперь это работает нормально, и вот несколько примеров того, как это работает:
+ => command: '+', args: nil
sum<5> => command: 'sum', args: '5'
print<1, 2, 3> => command: 'print', args: '1, 2, 3'
Это работает именно так, как я хочу для каждого, но последний. У меня вопрос, есть ли способ захватить каждый аргумент отдельно? Я имею в виду, как это:
print<1, 2, 3> => command: 'print', args: ['1', '2', '3']
Кстати, я использую последний движок Ruby regex.
1 ответ
Невозможно получить такой вывод, используя простое регулярное выражение с повторяющимися группами захвата в регулярном выражении Ruby, поскольку движок не сохраняет стек захвата.
Вам нужно разделить второй захват с ,
как шаг после процесса.
Смотрите демо Ruby:
def cmd_split(s)
rx = /(?<command>[^<>\s]+)(<(?<args>(\d+)+(?:,\s*\d+)*)>)?/
res = []
s.scan(rx) {
res << ($~[:args] != nil ?
Hash["command", $~[:command], "args", $~[:args].split(/,\s*/)] :
Hash[$~[:command], ""]) }
return res
end
puts cmd_split("print<1, 2, 3>") # => {"command"=>"print", "args"=>["1", "2", "3"]}
puts cmd_split("disp<1>") # => {"command"=>"disp", "args"=>["1"]}
puts cmd_split("+") # => {"+"=>""}