Существует ли принятый способ иметь дело с регулярными выражениями в Ruby 1.9, для которого кодирование входа неизвестно? Скажем, мой вход, оказывается, закодированный UTF-16:
x = "foo<p>bar</p>baz"
y = x.encode('UTF-16LE')
re = /<p>(.*)<\/p>/
x.match(re)
=> #<MatchData "<p>bar</p>" 1:"bar">
y.match(re)
Encoding::CompatibilityError: incompatible encoding regexp match (US-ASCII regexp with UTF-16LE string)
Мой текущий подход должен использовать UTF-8 внутренне и повторно закодировать (копия) вход при необходимости:
if y.methods.include?(:encode) # Ruby 1.8 compatibility
if y.encoding.name != 'UTF-8'
y = y.encode('UTF-8')
end
end
y.match(/<p>(.*)<\/p>/u)
=> #<MatchData "<p>bar</p>" 1:"bar">
Однако это чувствует себя немного неловким мне, и я хотел спросить, существует ли лучший способ сделать это.
Насколько мне известно, лучшего метода не существует. Однако, могу ли я предложить небольшое изменение?
Вместо того, чтобы менять кодировку входного сигнала, почему бы не изменить кодировку регекса? Перевод одной строки регекса каждый раз, когда вы встречаете новую кодировку, гораздо менее трудоемкий, чем перевод сотен или тысяч строк входного текста в соответствии с кодировкой вашего регекса.
# Utility function to make transcoding the regex simpler.
def get_regex(pattern, encoding='ASCII', options=0)
Regexp.new(pattern.encode(encoding),options)
end
# Inside code looping through lines of input.
# The variables 'regex' and 'line_encoding' should be initialized previously, to
# persist across loops.
if line.methods.include?(:encoding) # Ruby 1.8 compatibility
if line.encoding != last_encoding
regex = get_regex('<p>(.*)<\/p>',line.encoding,16) # //u = 00010000 option bit set = 16
last_encoding = line.encoding
end
end
line.match(regex)
В патологическом случае (когда входная кодировка меняет каждую строку) это было бы так же медленно, так как вы перекодируете регекс каждый раз в цикле. Но в 99.9% ситуаций, когда кодировка постоянна для целого файла, состоящего из сотен или тысяч строк, это приведет к значительному сокращению перекодирования
.Следуйте советам этой страницы: http://gnuu.org/2009/02/02/ruby-19-common-problems-pt-1-encoding/ и добавьте
# encoding: utf-8
в начало вашего rb файла.