a ASCII
n NONE (ASCII)
е EUC
s SJIS
u UTF-8
Для ясности можно пользоваться и полными названиями (например, $KCODE ="UTF-8"). Важен только первый символ.
О кодировке ASCII мы уже знаем. EUC и Shift-JIS (SJIS) нам малоинтересны. Мы сосредоточимся на значении UTF-8.
Установив значение $KCODE, вы задаром получаете весьма богатую функциональность. Например, метод inspect(он автоматически вызывается при обращении к методу pдля печати объекта в читаемом виде) обычно учитывает текущее значение $KCODE.
$KCODE = "n"
# Для справки: французское слово "épée"
# обозначает разновидность меча (sword).
eacute = ""
eacute << 0303 << 0251 # U+00E9
sword = eacute + "p" + eacute + "e"
p eacute # "\303\251"
p sword # "\303\251p\303\251e"
$KCODE = "u"
p eacute # "é"
p sword # "épée"
Регулярные выражения в режиме UTF-8 тоже становятся несколько «умнее».
$KCODE = "n"
letters = sword.scan(/(.)/)
# [["\303"], ["\251"], ["p"], ["\303"], ["\251"], ["e"]]
puts letters.size # 6
$KCODE = "u"
letters = sword.scan(/(.)/)
# [["é"], ["p"], ["é"], ["e"]]
puts letters.size # 4
Библиотека jcodeпредоставляет также несколько полезных методов, например jlengthи each_char. Рекомендую включать эту библиотеку с помощью директивы requireвсякий раз, как вы работаете с кодировкой UTF-8.
В следующем разделе мы снова рассмотрим некоторые типичные операции со строками и регулярными выражениями. Заодно поближе познакомимся с jcode.
4.2.2. Возвращаясь к строкам и регулярным выражениям
При работе с UTF-8 некоторые операции ничем не отличаются. Например, конкатенация строк выполняется так же, как и раньше:
"éр" + "éе" # "épée"
"éр" << "éе" # "épée"
Поскольку UTF-8 не имеет состояния, то для проверки вхождения подстроки тоже ничего специально делать не нужно:
"épée".include?("é") # true
Однако при написании интернациональной программы некоторые типичные допущения все же придется переосмыслить. Ясно, что символ больше не эквивалентен байту. При подсчете символов или байтов надо думать о том, что именно мы хотим сосчитать и для чего. То же относится к числу итераций.
По общепринятому соглашению, кодовую позицию часто представляют себе как «программистский символ». Это еще одна полуправда, но иногда она оказывается полезной.
Метод jlengthвозвращает число кодовых позиций в строке, а не байтов. Если нужно получить число байтов, пользуйтесь методом length.
$KCODE = "u"
require 'jcode'
sword = "épée"
sword.jlength # 4
sword.length # 6
Такие методы, как upcaseи capitalize, обычно неправильно работают со специальными символами. Это ограничение текущей версии Ruby. (Не стоит считать ошибкой, поскольку получить представление слова с первой прописной буквой довольно трудно; такая задача просто не решается в схеме интернационализации Ruby. Считайте, что это нереализованное поведение.)
$KCODE = "u"
sword.upcase # "ÉPÉE"
sword.capitalize # "épée"
Если вы не пользуетесь монолитной формой, то в некоторых случаях метод может сработать, поскольку латинские буквы отделены от диакритических знаков. Но в общем случае работать не будет — в частности, для турецкого, немецкого, голландского и любого другого языка с нестандартными правилами преобразования регистра.
Возможно, вы думаете, что неакцентированные символы в некотором смысле эквивалентны своим акцентированным вариантам. Это почти всегда не так. Здесь мы имеем дело с разными символами. Убедимся в этом на примере метода count:
$KCODE = "u"
sword.count("e") # 1 (не 3)
Но для составных (не монолитных) символов верно прямо противоположное. В этом случае латинская буква распознается.
Метод countвозвращает сбивающий с толку результат, когда ему передается многобайтовый символ. Метод jcountведет себя в этом случае правильно:
$KCODE = "u"
sword.count("eé") # 5 (не 3)
sword.jcount("eé") # 3
Существует вспомогательный метод mbchar?, который определяет, есть ли в строке многобайтовые символы.
$KCODE = "u"
sword.mbchar? # 0 (смещение первого многобайтового символа)
"foo".mbchar? # nil
В библиотеке jcodeпереопределены также методы chop, delete, squeeze, succ, trи tr_s. Применяя их в режиме UTF-8, помните, что вы работаете с версиями, «знающими о многобайтовости». При попытке манипулировать многобайтовыми строками без библиотеки jcodeвы можете получить странные или ошибочные результаты.
Читать дальше
Конец ознакомительного отрывка
Купить книгу