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
вы можете получить странные или ошибочные результаты.
Читать дальше
Конец ознакомительного отрывка
Купить книгу