【问题标题】:Ruby 1.9: Regular Expressions with unknown input encodingRuby 1.9:输入编码未知的正则表达式
【发布时间】:2009-12-21 19:37:28
【问题描述】:

在 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">

但是,这对我来说有点尴尬,我想问一下是否有更好的方法。

【问题讨论】:

    标签: ruby regex encoding character-encoding


    【解决方案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% 的情况下,对于数百或数千行的整个文件的编码是恒定的,这将导致重新编码的大量减少。

    【讨论】:

    • 谢谢!我没有想到要反过来对正则表达式进行编码。这确实快了很多!对于其他尝试这样做的人:当您尝试测试代码时,请注意虚拟编码 (#dummy?)。我花了一段时间才弄清楚为什么它不起作用。
    • 同意性能 - 我发现记忆正则表达式的速度呈指数级增长。在这里快速破解空格剥离:gist.github.com/mahemoff/c877eb1e955b1160dcdf6f4d4c0ba043
    【解决方案2】:

    遵循此页面的建议:http://gnuu.org/2009/02/02/ruby-19-common-problems-pt-1-encoding/ 并添加

    # encoding: utf-8
    

    到你的 rb 文件的顶部。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-20
      • 2011-07-15
      • 2011-08-08
      • 1970-01-01
      • 2011-08-06
      • 1970-01-01
      相关资源
      最近更新 更多