使用\ d扫描字符串中的Unicode数字
根据Oniguruma文档 , \d
字符类型匹配:
十进制数字char
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"]
我误读了文档吗? 为什么不匹配其他Unicode数字,和/或有没有办法让它这样做?
Brian Candler在ruby谈话中注意到:
-
\w
仅匹配ASCII字母和数字,而[[:alpha:]]
匹配整套Unicode字母。 -
\d
仅匹配ASCII数字,而[[:digit:]]
匹配整个Unicode数字集。
因此行为是“一致的”,我们有一个简单的Unicode数字解决方法。 在同一个Oniguruma文档中阅读\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来说并不准确 。 查看此票证讨论 ,包括以下post:
[Yui 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
请尝试使用Unicode字符类\p{N}
。 这匹配所有Unicode数字。 不知道为什么\d
不起作用。
\d
默认情况下仅匹配ASCII数字。 您可以使用(反直觉) (?u)
语法在正则表达式中手动打开Unicode匹配:
"𝟛".match(/(?u)\d/) # => #
或者,您可以在正则表达式中使用“posix”或“unicode property”样式,这不需要您手动打开Unicode匹配:
/[[:digit:]]/ # posix style /\p{Nd}/ # unicode property/category style
您可以在以下博客文章中找到有关如何在Ruby中对Unicode字符进行高级匹配的更多详细信息: http : //idiosyncratic-ruby.com/30-regex-with-class.html