Есть ли способ передать захват регулярных выражений в блок в Ruby? - PullRequest
1 голос
/ 18 января 2011

У меня есть хеш с regex для ключа и block для значения.Что-то вроде следующего:

{ 'test (.+?)' => { puts $1 } }

Не точно , как это, очевидно, поскольку блок хранится как Proc, но это идея.

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

hash.each do |pattern, action|
    if /#{pattern}/i.match(string)
        action.call
    end
end

Идея заключалась в том, чтобы сохранить блок в хэше, чтобы мне было легче расширяться в будущем, но теперьregex захват не передается в блок.Есть ли способ сделать это чисто, который бы поддерживал любое количество захватов, которые я вставил в regex (например, в некоторых шаблонах regex может быть 1 захват, в других - 3)?

Ответы [ 2 ]

3 голосов
/ 18 января 2011

Что, если вы передадите данные о совпадениях в свои процы?

hash.each do |pattern, action|
  if pattern.match(string)
    action.call($~)
  end
end

Ваш хэш станет:

{ /test (.+?)/i => lambda { |matchdata| puts matchdata[1] } }
1 голос
/ 18 января 2011

Я бы использовал Hash.find, который обходит элементы хеша, передавая их в блок, по одному за раз.Тот, который возвращает true, выигрывает:

Примерно так:

hash = {/foo/ => lambda { 'foo' }, /bar/ => lambda { 'bar' } }
str = 'foo'
puts hash.find{ |n,v| str =~ n }.to_a.last.call

Очевидно, я использую lambda, но это достаточно близко.И, если не было совпадений, вам нужно обработать нулевые значения.Для примера, который я приковал to_a.last.call, но в реальной жизни вы захотите отреагировать на ноль, иначе Руби разозлится.

Если вы просматриваете много шаблонов или обрабатываете много текста,Ваш поиск будет замедлен из-за необходимости каждый раз перекомпилировать регулярное выражение.Я бы рекомендовал хранить ключи как объекты регулярных выражений, чтобы избежать этого.

...