Сканирование номеров Юникода в строке с помощью \ d - PullRequest
8 голосов
/ 09 августа 2011

Согласно документации 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, и / или есть ли способ сделать это?

Ответы [ 3 ]

2 голосов
/ 10 августа 2011

Отмечено Брайаном Кэндлером на ruby-talk :

  • \w соответствует только буквам и цифрам ASCII, а [[:alpha:]] соответствует полному набору букв Unicode.
  • \d соответствует только цифрам ASCII, а [[:digit:]] соответствует полному набору номеров Unicode.

Таким образом, поведение является «последовательным», и у нас есть простой обходной путь для чисел Юникода. Читая \w в тот же документ Oniguruma мы видим текст:

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

В свете реального поведения Ruby и вышеприведенного текста "Not Unicode" может показаться, что в документации описываются два режима - режим Unicode и режим Not Unicode & mdash; и что Ruby работает в режиме Not Unicode .

Это объясняет, почему \d не соответствует полному набору Unicode: хотя документация Oniguruma не в состоянии точно описать то, что соответствует, когда в режиме не Unicode, теперь мы знаем, что поведение, задокументированное как "Unicode", не должно быть ожидается.

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

Читателю оставлено в качестве упражнения узнать, как (если это вообще возможно) включить режим Unicode в регулярных выражениях Ruby, поскольку флаг /u (например, /\w/u) этого не делает. (Возможно, Ruby нужно перекомпилировать со специальным флагом для Онигурума.)

Обновление : может показаться, что документ Онигурума, на который я ссылаюсь , не подходит для Ruby 1.9 . См. обсуждение этого билета , включая следующие сообщения:

[Yui NARUSE] "RE.txt для оригинального Oniguruma, а не для регулярного выражения Ruby 1.9. Нам может понадобиться наш собственный документ."
[Matz] «Наш Онигурума разветвлен. Оригинальный Онигурума, найденный в geocities.jp, не был изменен».

Лучшая справка : Вот официальная документация по синтаксису регулярного выражения Ruby 1.9:
https://github.com/ruby/ruby/blob/trunk/doc/re.rdoc

1 голос
/ 26 марта 2016

\d будет соответствовать только для чисел ASCII по умолчанию. Вы можете вручную включить сопоставление Юникода в регулярном выражении, используя (нелогичный) синтаксис (?u):

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

Кроме того, вы можете использовать стиль "posix" или "свойство unicode" в своем регулярном выражении, которое не требует, чтобы вы вручную включали сопоставление Unicode:

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

Более подробную информацию о том, как выполнить расширенное сопоставление для символов Юникода в Ruby, можно найти в этом сообщении в блоге: http://idiosyncratic -ruby.com / 30-регулярное выражение-с-class.html

1 голос
/ 09 августа 2011

Попробуйте использовать класс символов Unicode \p{N}.Это соответствует всем цифрам Unicode.Понятия не имею, почему \d не работает.

...