Ruby 1.9: Регулярные выражения с неизвестной кодировкой ввода

Существует ли приемлемый способ работы с регулярными выражениями в 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">

Однако для меня это немного неудобно, и я хотел спросить, есть ли лучший способ сделать это.

Ответы

Ответ 1

Насколько мне известно, нет лучшего метода для использования. Однако могу ли я предложить небольшое изменение?

Вместо того, чтобы изменять кодировку ввода, почему бы не изменить кодировку регулярного выражения? Перевод одной строки регулярного выражения каждый раз, когда вы встречаете новую кодировку, намного меньше, чем перевод сотен или тысяч строк ввода в соответствии с кодировкой вашего регулярного выражения.

# 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% случаев, когда кодирование является постоянным для целого файла сотен или тысяч строк, это приведет к значительному сокращению повторного кодирования.