Сканирование номеров Юникода в строке с помощью \d
Согласно документации 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 ответа
Отмеченный Брайаном Кэндлером на ruby-talk:
\w
соответствует только буквам и цифрам ASCII, а[[:alpha:]]
соответствует полному набору букв Unicode.\d
соответствует только цифрам ASCII, а[[:digit:]]
соответствует полному набору номеров Unicode.
Таким образом, поведение является "последовательным", и у нас есть простой обходной путь для номеров Unicode. Чтение на \w
в том же документе Онигурума мы видим текст:
\w word character
Not Unicode: alphanumeric, "_" and multibyte char.
Unicode: General_Category -- (Letter|Mark|Number|Connector_Punctuation)
В свете реального поведения Ruby и вышеприведенного текста "Not Unicode" может показаться, что в документации описываются два режима - режим Unicode и режим Not Unicode - и что 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 со специальным флагом для Oniguruma.)
Обновление: может показаться, что документ Oniguruma, на который я ссылаюсь, не является точным для 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
Попробуйте использовать символьный класс Unicode \p{N}
вместо. Это соответствует всем цифрам Unicode. Не знаю почему \d
не работает
\d
будет соответствовать только для ASCII номеров по умолчанию. Вы можете вручную включить сопоставление Юникода в регулярном выражении, используя (нелогично) (?u)
синтаксис:
"".match(/(?u)\d/) # => #<MatchData "">
Кроме того, вы можете использовать стиль "posix" или "свойство unicode" в своем регулярном выражении, которое не требует, чтобы вы вручную включали сопоставление Unicode:
/[[:digit:]]/ # posix style
/\p{Nd}/ # unicode property/category style
Более подробную информацию о том, как выполнить расширенное сопоставление символов Unicode в Ruby, можно найти в этом сообщении в блоге: http://idiosyncratic-ruby.com/30-regex-with-class.html