Чтение онлайн

на главную - закладки

Жанры

Программирование на языке Ruby
Шрифт:

sword.each_byte {|x| puts x } # Шесть строк с целыми числами.

sword.each_char {|x| puts x } # Четыре строки со строками.

Если вы запутались, не переживайте. Все мы через это проходили. Я попытался свести все вышесказанное в таблицу 4.1.

Таблица 4.1. Составные и монолитные формы

Монолитная форма "'e"
Название символа Глиф Кодовая позиция Байты UTF-8 Примечания
Строчная латинская e с акутом 'e U+00E9 0xC3 0хА9 Один символ, одна кодовая позиция, один байт
Составная форма "'e"
Название символа Глиф Кодовая позиция Байты UTF-8 Примечания
Строчная латинская е е U+0065 0x65 Один символ, две кодовых позиции (два «программистских символа»), три байта UTF-8
Модифицирующий акут U+0301 0xCC 0x81

Что еще надо учитывать при работе с интернациональными строками? Квадратные скобки по-прежнему относятся к байтам, а не к символам. Но при желании это можно изменить. Ниже приведена одна из возможных реализаций (не особенно эффективная, зато понятная):

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*') # "'ep'ee"

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

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

cafe = "caf#{eacute}" # "caf'e"

Регулярным выражениям тоже известно о многобайтовых символах, особенно если вы пользуетесь библиотекой 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. Я - Легенда!
Фантастика:
боевая фантастика
рпг
попаданцы
5.00
рейтинг книги
Геном хищника. Книга четвертая

Анна Иоановна

Сахаров Андрей Николаевич
9. Романовы. Династия в романах
Проза:
историческая проза
5.60
рейтинг книги
Анна Иоановна

Влечение

Усачева Елена Александровна
1. Пленники сумерек
Любовные романы:
современные любовные романы
8.02
рейтинг книги
Влечение

Последний Паладин. Том 11

Саваровский Роман
11. Путь Паладина
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Последний Паладин. Том 11

Первый среди равных. Книга X

Бор Жорж
10. Первый среди Равных
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Первый среди равных. Книга X

Газлайтер. Том 27

Володин Григорий Григорьевич
27. История Телепата
Фантастика:
боевая фантастика
попаданцы
аниме
5.25
рейтинг книги
Газлайтер. Том 27

Петербург - нуар. Рассказы

Кивинов Андрей Владимирович
Проза:
современная проза
5.40
рейтинг книги
Петербург - нуар. Рассказы

Осторожно! Мины!

Шакилов Александр
Фантастика:
боевая фантастика
5.75
рейтинг книги
Осторожно! Мины!

Обреченная

Макдевит Джек
2. Космоархеологи
Фантастика:
научная фантастика
7.00
рейтинг книги
Обреченная

Академия

Сай Ярослав
2. Медорфенов
Фантастика:
юмористическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Академия

Нью-Йорк

Резерфорд Эдвард
The Big Book
Проза:
историческая проза
6.00
рейтинг книги
Нью-Йорк

Первый среди равных. Книга V

Бор Жорж
5. Первый среди Равных
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Первый среди равных. Книга V

Дважды одаренный. Том V

Тарс Элиан
5. Дважды одаренный
Фантастика:
аниме
альтернативная история
городское фэнтези
5.25
рейтинг книги
Дважды одаренный. Том V

Я еще не царь

Дрейк Сириус
25. Дорогой барон!
Фантастика:
юмористическое фэнтези
аниме
попаданцы
5.00
рейтинг книги
Я еще не царь