2011-01-17 2 views
1

У меня есть хэш с regex для ключа и block для значения. Что-то вроде следующего:Есть ли способ передать захват регулярных выражений блоку в Ruby?

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

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

Я тогда регулярное выражение матч позже на том, что выглядит как этого

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

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

+0

Это не касается вашего вопроса, но зачем хранить шаблон как строку вместо регулярного выражения? – cam

+0

Нет настоящей причины. Я использую метод для хранения хэша, поэтому его легче читать ('on (pattern, & block) hash [pattern] = block' - это в основном метод, который я использую), и казалось, что проще написать' on 'test (. +?) 'делает $ 1 end'. –

ответ

3

Что делать, если вы передаете данные о совпадении в свои procs?

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

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

{ /test (.+?)/i => lambda { |matchdata| puts matchdata[1] } } 
+0

Спасибо. Мне пришлось использовать 'matchdata [1]' вместо 'first', но это отлично работает. –

+0

О, хорошо, я должен был проверить это первым. Я изменил свой ответ ради будущего. – cam

1

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

что-то вроде этого:

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

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

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