вторник, 1 марта 2011 г.

Ruby: Небольшой нюанс обработки Regexp в блоках

Столкнулся со следующим, неожиданным для меня, поведением метода gsub() с блоком кода — если мы этот блок указываем не непосредственно, а берем откуда-то еще, то в нем не работают, как им положено, переменные $1, $2 и так далее.

Т.е. следующий код:

#!/usr/bin/ruby

ds = "[b]Hello[/b] World!"
dr = /\[[bB](.*)\](.*)\[\/[bB]\]/m
dp = proc { |match| "#{$1}<b>#{$2}</b>" }

p ds.gsub(dr, &dp)

$~ = nil

def str_gsub(str, pattern, &block)
  str.gsub(pattern, &block)
end

p str_gsub(ds, dr, &dp)

Выдает:

"<b>Hello</b> World!"
"<b></b> World!"

То, что в примере все значения сохранены в переменные, сделано исключительно для удобства публикации. Результаты те же и в случае, когда используются значения непосредственно.

Выход — передавать содержимое $~ явно:

def str_gsub2(str, pattern, &block)
  str.gsub(pattern) { block.call $~ }
end

p str_gsub2(ds, dr) { |m| "#{m[1]}<b>#{m[2]}</b>" }

Блок при этом, естественно, нужен уже другой, но в моем случае это не важно, важна возможность использовать переданные и сохраненные блоки кода сами по себе.

Комментариев нет:

Отправить комментарий