class String

 def [](index)

  self.scan(/./)[index]

 end

 def []=(index,value)

  arr = self.scan(/./)

  arr[index] = value

  self.replace(arr.join)

  value

 end

end

Конечно, здесь не реализована значительная часть функциональности настоящего метода [], который понимает диапазоны, регулярные выражения и т.д. Если вам все это нужно, придется запрограммировать самостоятельно.

У метода unpack есть параметры, помогающие манипулировать Unicode-строками. Указав в форматной строке параметр U*, мы можем преобразовать строку в кодировке UTF-8 в массив кодовых позиций (U без звездочки преобразует только первую кодовую позицию):

codepoints = sword.unpack('U*') # [233, 112, 233, 101]

Вот несколько более полезный пример, в котором все кодовые позиции в строке, отличные от ASCII (то есть начиная с U+0080), преобразуются к виду U+XXXX, который мы обсуждали выше:

def reveal_non_ascii(str)

 str.unpack('U*').map do |cp|

 if cp < 0x80

  cp.chr

 else

  '(U+%04X)' % cp

 end

 end.join

end

У метода String#unpack есть «близкий родственник» Array#pack, выполняющий обратную операцию:

[233, 112, 233, 101].pack('U*') # 'épée'

Мы можем воспользоваться им, чтобы вставить Unicode-символы, которые трудно ввести с клавиатуры:

eacute = [0хЕ9].pack('U')

cafe = 'caf#{eacute}' # 'café'

Регулярным выражениям тоже известно о многобайтовых символах, особенно если вы пользуетесь библиотекой Oniguruma (мы рассматривали ее в главе 3). Например, образец /./ сопоставляется с одним многобайтовым символом.

Модификатор u извещает регулярное выражение о том, что мы работаем с кодировкой UTF-8. Если $KCODE равно 'u', то модификатор можно не задавать, однако это и не повредит. (К тому же такая избыточность может быть полезна, если код является частью большой программы, а какое значение переменной $KCODE в ней установлено, вам неизвестно.)

Даже без Oniguruma регулярные выражения распознают, относится ли данный многобайтовый символ к категории тех, что могут входить в состав слова:

$KCODE = 'u'

sword =~ /w/ #0

sword =~ /W/ # nil

При наличии Oniguruma последовательности, начинающиеся с символа обратной косой черты (w, s и т.п.) распознают и более широкие диапазоны кодовых точек: слова, пропуски и т.д.

Регулярные выражения позволяют безопасно выполнять простые манипуляции со строками. Мы и так можем без труда усекать строки. Следующий код возвращает не более 20 символов из строки ascii_string:

ascii_string[0,20]

Однако, поскольку кодовая позиция Unicode может занимать более одного байта такую технику нельзя безопасно применять к строке в кодировке UTF-8. Есть риск, что в конце строки окажется недопустимая последовательность байтов. Кроме того, это не слишком полезно, так как мы не можем заранее сказать, сколько в результате получится кодовых позиций. На помощь приходят регулярные выражения:

def truncate(str, max_length)

 str[/.{0,#{max_length}}/m]

end

4.2.3. Распознавание кодировки

Распознать, в какой кодировке записана данная строка, довольно сложно. Многобайтовые кодировки обладают отличительными признаками, по которым их можно опознать, но с однобайтовыми — а именно они применяются в западных языках — дело обстоит куда хуже. Для решения можно применить статистические методы, но эта тема выходит за рамки данной книги (к тому же результат в общем случае получается не слишком надежным).

К счастью, обычно перед нами стоит более простая задача — выяснить, записана ли строка в кодировке UTF-8. На этот вопрос можно дать достаточно надёжный ответ. Приведем один способ (основанный на том, что метод unpack возбуждает исключение, если ему передана некорректная строка):

class String

 def utf8?

  unpack('U*') rescue return false

  true

 end

end

4.2.4. Нормализация Unicode-строк

До сих пор мы пользовались монолитными символами, в которых базовый символ и диакритический знак объединены в одну кодовую позицию. Но, вообще говоря, в Unicode символы и диакритические знаки представлены отдельно. Вместо того чтобы хранить букву é в кодовой позиции СТРОЧНАЯ ЛАТИНСКАЯ БУКВА E С АКУТОМ, можно было бы представить ее в составной форме как СТРОЧНУЮ ЛАТИНСКУЮ БУКВУ E и МОДИФИЦИРУЮЩИЙ АКУТ.

Для чего это может понадобиться? Для обеспечения дополнительной гибкости и возможности

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату