使用\ d扫描字符串中的Unicode数字

时间:2011-08-09 15:28:22

标签: ruby regex unicode character-properties

根据the Oniguruma documentation\d字符类型匹配:

  

十进制数字

  Unicode:General_Category - Decimal_Number

但是,在包含所有Decimal_Number字符的字符串中扫描\d会导致仅匹配拉丁语0-9位数:

#encoding: utf-8
require 'open-uri'
html = open("http://www.fileformat.info/info/unicode/category/Nd/list.htm").read
digits = html.scan(/U\+([\da-f]{4})/i).flatten.map{ |s| s.to_i(16) }.pack('U*')

puts digits.encoding, digits
#=> UTF-8
#=> 0123456789٠١٢٣٤٥٦٧٨٩۰۱۲۳۴۵۶۷۸۹߀߁߂߃߄߅߆߇߈߉०१२३४५६७८९০১২৩৪৫৬৭৮৯੦੧੨…

p RUBY_DESCRIPTION, digits.scan(/\d/)
#=> "ruby 1.9.2p180 (2011-02-18) [i386-mingw32]"
#=> ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]

我误读了文档吗?为什么\d不匹配其他Unicode数字,和/或有没有办法让它这样做?

3 个答案:

答案 0 :(得分:2)

Brian Candler on ruby-talk注意到:

  • \w仅匹配ASCII字母和数字,而[[:alpha:]]匹配整套Unicode字母。
  • \d仅匹配ASCII数字,而[[:digit:]]匹配整套Unicode数字。

因此行为是“一致的”,我们对Unicode数字有一个简单的解决方法。阅读the same Oniguruma doc中的\w,我们会看到文字:

\w  word character  
    Not Unicode: alphanumeric, "_" and multibyte char.  
    Unicode: General_Category -- (Letter|Mark|Number|Connector_Punctuation)

鉴于Ruby的真实行为和上面的“非Unicode”文本,文档似乎描述了两种模式 - Unicode模式和非Unicode模式 - 并且Ruby在非Unicode模式下运行

这可以解释为什么\d与完整的Unicode集不匹配:虽然Oniguruma文档无法准确描述在非Unicode模式下匹配的内容,但我们现在知道记录为“Unicode”的行为不是可以预料。

p "abç".scan(/\w/), "abç".scan(/[[:alpha:]]/)
#=> ["a", "b"]
#=> ["a", "b", "\u00E7"]

让读者了解如何(如果有的话)在Ruby regexp中启用Unicode模式,因为/u标志(例如/\w/u)没有这样做。 (也许Ruby必须使用Oniguruma的特殊标志重新编译。)

更新:似乎我链接到的Oniguruma文档对于Ruby 1.9来说不准确。请参阅this ticket discussion,包括这些帖子:

   NARUSE]“RE.txt适用于原始Oniguruma,不适用于Ruby 1.9的正则表达式。我们可能需要自己的文档。”
  [Matz]“我们的Oniguruma是分叉的。在geocities.jp中找到的原始Oniguruma没有改变。”

更好的参考:这是关于Ruby 1.9的regexp语法的官方文档:
https://github.com/ruby/ruby/blob/trunk/doc/re.rdoc

答案 1 :(得分:1)

请尝试使用Unicode字符类\p{N}。这匹配所有Unicode数字。不知道为什么\d无效。

答案 2 :(得分:1)

默认情况下,

\d仅匹配ASCII数字。您可以使用(反直觉)(?u)语法手动打开正则表达式中的Unicode匹配:

"".match(/(?u)\d/) # => #<MatchData "">

或者,您可以在正则表达式中使用“posix”或“unicode property”样式,这不需要您手动打开Unicode匹配:

/[[:digit:]]/ # posix style
/\p{Nd}/ # unicode property/category style

您可以在此博客文章中找到有关如何在Ruby中对Unicode字符进行高级匹配的更多详细信息: http://idiosyncratic-ruby.com/30-regex-with-class.html