Хэл Фултон - Программирование на языке Ruby Страница 35

Тут можно читать бесплатно Хэл Фултон - Программирование на языке Ruby. Жанр: Компьютеры и Интернет / Программирование, год -. Так же Вы можете читать полную версию (весь текст) онлайн без регистрации и SMS на сайте «WorldBooks (МирКниг)» или прочесть краткое содержание, предисловие (аннотацию), описание и ознакомиться с отзывами (комментариями) о произведении.
Хэл Фултон - Программирование на языке Ruby

Хэл Фултон - Программирование на языке Ruby краткое содержание

Прочтите описание перед тем, как прочитать онлайн книгу «Хэл Фултон - Программирование на языке Ruby» бесплатно полную версию:
Ruby — относительно новый объектно-ориентированный язык, разработанный Юкихиро Мацумото в 1995 году и позаимствовавший некоторые особенности у языков LISP, Smalltalk, Perl, CLU и других. Язык активно развивается и применяется в самых разных областях: от системного администрирования до разработки сложных динамических сайтов.Книга является полноценным руководством по Ruby — ее можно использовать и как учебник, и как справочник, и как сборник ответов на вопросы типа «как сделать то или иное в Ruby». В ней приведено свыше 400 примеров, разбитых по различным аспектам программирования, и к которым автор дает обстоятельные комментарии.Издание предназначено для программистов самого широкого круга и самой разной квалификации, желающих научиться качественно и профессионально работать на Ruby.

Хэл Фултон - Программирование на языке Ruby читать онлайн бесплатно

Хэл Фултон - Программирование на языке Ruby - читать книгу онлайн бесплатно, автор Хэл Фултон

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

Можно побайтно просматривать строку, как обычно, с помощью итератора each_byte. А можно просматривать посимвольно с помощью итератора each_char. Второй способ имеет дело с односимвольными строками, первый (в текущей версии Ruby) — с однобайтными целыми. Разумеется, мы в очередной раз приравниваем кодовую позицию к символу. Несмотря на название, метод each_char на самом деле перебирает кодовые позиции, а не символы.

$KCODE = "u"

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

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

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

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

Монолитная форма "é" Название символа Глиф Кодовая позиция Байты UTF-8 Примечания Строчная латинская e с акутом é U+00E9 0xC3 0хА9 Один символ, одна кодовая позиция, один байт Составная форма "é" Название символа Глиф Кодовая позиция Байты 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*') # "é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:

Перейти на страницу:
Вы автор?
Жалоба
Все книги на сайте размещаются его пользователями. Приносим свои глубочайшие извинения, если Ваша книга была опубликована без Вашего на то согласия.
Напишите нам, и мы в срочном порядке примем меры.
Комментарии / Отзывы
    Ничего не найдено.