8

根据Oniguruma 文档\d字符类型匹配:

十进制数字字符
Unicode:General_Category -- Decimal_Number

但是,\d在包含所有 Decimal_Number 字符的字符串中进行扫描会导致仅匹配拉丁语 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 数字,和/或有办法让它匹配?

4

3 回答 3

2

Brian Candler 在 ruby​​-talk 上指出:

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

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

\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 正则表达式中启用 Unicode 模式,因为/u标志(例如/\w/u)不这样做。(也许 Ruby 必须使用 Oniguruma 的特殊标志重新编译。)

更新:看来我链接到的 Oniguruma 文档对于 Ruby 1.9 是不准确的。请参阅此票务讨论,包括以下帖子:

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

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

于 2011-08-09T22:30:27.797 回答
1

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

于 2011-08-09T15:54:22.747 回答
1

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

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

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

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

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

于 2016-03-26T14:24:34.740 回答