Ruby/Подробнее о строках: различия между версиями

Нет описания правки
'''Искусственное дыхание''' — комплекс мер, направленных на поддержание оборота воздуха через легкие у человека (или животного), переставшего дышать. Может производиться с помощью аппарата искусственного дыхания, либо человеком (дыхание изо рта в рот). Обычно совмещается с [[искусственный массаж сердца|искусственным массажем сердца]]. Типичные ситуации, в которых требуется искусственное дыхание: несчастные случаи в результате автомобильных аварий, происшествия на воде, поражение электрическим током, утопление. Аппарат искусственного дыхания используется также в хирургических операциях.
== Подробнее о строках ==
 
=== Искусственное дыхание «рот-в-рот» ===
Строка — это упорядоченная последовательность символов, которая располагается между ограничительными символами.
[[Изображение:ArificialBreath.JPG|thumb|260 px|right|Искусственное дыхание «рот-в-рот»]]
Наиболее эффективный способ искусственного дыхания.
# Спасите пострадавшего, уберите от него ток, если он им поражён, вытащите из воды при утоплении, обеспечьте его безопасность.
# Положите пострадавшего на спину. Откройте ему рот, следите, чтобы язык не закрывал гортань.
# Одной рукой удерживайте голову и шею пострадавшего, другой зажмите его нос. Глубоко вдохните и, плотно прижавшись ртом ко рту, сделайте выдох.
# Первые 5—10 выдохов делайте быстро (за 20—30 с), следующие— со скоростью 12—15 выдохов в минуту.
# Следите за движением грудной клетки пострадавшего: если после вашего выдоха в рот его грудная клетка поднялась, значит, дыхательные пути проходимы и искусственное дыхание вы делаете правильно.
# Если нет пульса, параллельно с искусственным дыханием необходимо делать массаж сердца.
 
=== Искусственное дыхание «рот-в-нос» ===
Строковый тип является самым популярным в любом языке программирования. Ведь без него невозможно написать любую программу (особенно учитывая, что любая программа — это строка). При выводе на экран или записи в файл, любой тип данных преобразуется к строке (явно или неявно). Это значит, что в конечном итоге всё сводится к строковому типу. Кстати, и ввод данных тоже осуществляется в виде строки (и только потом преобразуется в другие типы).
Проводится, если рот спасаемого повреждён или по каким-либо причинам нельзя использовать метод «рот-в-рот». Не так эффективно, как искусственное дыхание «рот-в-рот», «рот-в-нос» также способно спасти человека.
 
== См. также ==
{{info|Студенты четвёртого курса МЭТТ ГАИ поступили на подготовительные курсы в [[w:Московский государственный индустриальный университет|МГИУ]]. Там им начали преподавать основы программирования на Ruby. И одна из заданных им задач была: «Дано число, необходимо поменять порядок цифр на обратный». Задача сложная, но наши студенты об этом не знали и решили её преобразованием к строке: <code>given.to_s.reverse</code>. Преподаватели были поражены и впредь запретили им использовать преобразования к строке в своих программах. И всё потому, что это сильно упрощало решение и давало студентам огромное преимущество перед остальными слушателями курсов.}}
* [[Реанимация]]
* [[Искусственный массаж сердца]]
 
[[Категория:Дыхание]]
Язык Ruby унаследовал работу со строками из языка Perl (признанного лидера по работе со строками). В частности такой мощный инструмент как правила (rules).
[[Категория:Медицина]]
 
[[Категория:Первая помощь]]
Но наследование не подразумевает бездумного копирования. В частности, правила, в рамках Ruby, получили объектно-ориентированную реализацию, что позволяет применять к ним различные методы. Помимо правил, присутствует великое множество методов работы со строками. Причём некоторые из них являются нашими старыми знакомыми (<code>+</code>, <code>*</code>, <code>[]</code> и так далее). Работают они несколько иначе, но некоторая параллель с массивами все же присутствует.
[[Категория:Искусственное дыхание]]
Следует упомянуть два очень интересных момента:
 
* Cтроки — это универсальный тип данных, так как в строку можно преобразовать любой другой тип данных. Также строку можно преобразовать в любой другой тип данных (ведь изначально любой код программы — это строка).
* Cтроки очень удобно преобразовывать в массив и обратно (методы <code>.join</code> и <code>.split</code>). Поэтому работа со строками практически столь же удобная, как и с массивами.
 
Если работа со строками обходится без преобразования в массив, то программа либо очень простая, либо бесполезная.
 
=== Способы создания строки ===
 
Строка создаётся при помощи ограничительных символов. Для этих целей чаще всего используются <code>"</code> (программистская кавычка) и <code>'</code> (машинописный апостроф). Их смысл различен. Строка в апострофах гарантирует, что в ней будет содержаться тот же текст, что и в коде программы, без изменений. Строка в кавычках будет проходить предварительное преобразование. Будут раскрыты конструкции «вставка» и «специальный символ».
 
<!--{{Начало цитаты}}
Зажатые в лапках работать хотят,<br />
а строки в минутах лениво сопят.
{{Конец цитаты}}
-->
Давайте будем называть строки в апострофах «ленивыми», а строки в кавычках — «работящими».
 
Вставка — это хитрая конструкция, которая вставляется между ограничительными символами внутри строки. Она состоит из комбинации [[w:Октоторп|октоторпа]] и двух фигурных скобок (<code><b>#{</b> 'здесь был Вася' <b>}</b></code>). Внутри неё можно писать не только <code>'Здесь был Вася'</code>, но и любой программный код. Результат программного кода будет преобразован к строке и вставлен на место вставки.
 
Вставка жизнью заправляет:<br />
Код программный выполняет,<br />
Тихо результат считает,<br />
Вместо вставки подставляет.
 
«Вставка» работает только в момент создания строки́. После создания придётся придумывать другие способы подстановки данных в стро́ки.
 
Специальный символ начинается со знака <code>\</code> ([[w:Обратная косая черта|обратная косая черта]]). Самые популярные из них: <code>\n</code> (переход на новую строку), <code>\t</code> ([[w:Табуляция|табуляция]]), <code>\\</code> (обратная косая черта) и <code>\"</code> ([[w:Кавычки|двойная кавычка]]).
 
Хотя специальный символ и пишется, как два знака, но на деле это всего один символ. Доказать это можно выполненением простенького кода: <code>"\n".size #=> 1</code>.
 
==== Для чего нужны работящие и ленивые строки? ====
 
Скорее всего вы будете редко вспоминать про то, что существуют работящие и ленивые строки. Тем более, что это различие действительно только на момент создания строки. Рядовой программист пользуется либо работящими, либо ленивыми строками. Давайте посмотрим, как выглядит код программиста, который использует только ленивые строки:
 
<source lang="ruby">my_number = 18
my_array = [1, 2, 3, 4]
puts 'Моё число = ' + my_number.to_s + ', а мой массив длины ' + my_array.size.to_s</source>
 
Обратите внимание, что перед сцеплением (умные дяди называют это конкатенацией) необходимо все данные преобразовывать к строке методом <code>.to_s</code>. Вставка позволяет этого избежать. Вот, как будет выглядеть та же самая программа с использованием вставки:
 
<source lang="ruby">my_number = 18
my_array = [1, 2, 3, 4]
puts "Моё число = #{my_number}, а мой массив длины #{my_array.size}"</source>
 
Программа стала не только меньше, но и лучше читаться. Исчезли многочисленные сцепления.
 
Если внутри вставки надо создать строку, то экранировать кавычки не сто́ит. Внутренности вставки не являются частью строки́, а значит живут по своим законам.
 
<source lang="ruby">my_array = [1, 2, 3, 4]
puts "Повторенье — мать ученья. Мой массив = #{my_array.join(\", \")}"</source>
 
Программа вызовет ошибку, так как внутри вставки было использовано экранирование кавычек. Правильный пример будет выглядеть так:
 
<source lang="ruby">my_array = [1, 2, 3, 4]
puts "Повторенье — мать ученья. Мой массив = #{my_array.join(", ")}"</source>
 
{{info|Нет необходимости в экранировании строк внутри вставки.}}
 
=== Методы работы со строками ===
 
Методы строк умеют:
 
* преобразовывать входные данные в красивый вид,
* красиво оформить выходные данные,
* дезертировать в массивы.
 
Допустим, вы нашли максимальный элемент массива. И вам надо вывести результат на экран.
Вы можете поступить вот так:
 
<source lang="ruby">array = [4, 4, 2, 5, 2, 7]
puts array.max #=> 7</source>
 
Несмотря на правильность решения, вывод результата выглядит некрасиво. Гораздо профессиональней будет написать вот такую программу:
 
<source lang="ruby">array = [4, 4, 2, 5, 2, 7]
puts "Максимальный элемент array = #{array.max}" #=> Максимальный элемент array = 7</source>
 
Заметили, насколько привлекательней стал вывод результата, когда мы задействовали стро́ки?
 
Заниматься оформлением выходных данных сто́ит только непосредственно перед выводом результата. В остальное время использование оформительских элементов будет только мешать.
 
Всем известно, что чи́сла внутри компьютера хранятся в двоичной системе. Но вот парадокс: получить двоичное представление числа иногда очень сложно. В частности, для того, чтобы получить двоичную запись числа, необходимо создать строку и записывать результат в неё. Это значит, что результатом преобразования в другую систему счисления (из десятичной) будет строка. Давайте посмотрим, как эта задача решается:
 
<source lang="ruby">
my_number = 123
puts "В двоичном виде: %b" % my_number #=> В двоичном виде: 1111011</source>
 
Мы задействовали метод <code>%</code> (аналог <code>sprintf</code> в Си), который осуществляет форматирование строки́. Эту же задачу можно решить несколько иначе.
 
<source lang="ruby">my_number = 123
puts "В двоичном виде: #{my_number.to_s(2)}" #=> В двоичном виде: 1111011</source>
 
Со вторым вариантом вы могли уже́ встречаться в разделе, посвящённом числам (подраздел Хитрости).
 
Методы <code>sprintf</code> и <code>printf</code> в Ruby также присутствуют, но по непонятным причинам используются крайне редко. Чаще всего они заменяются на методы <code>%</code> и <code>puts</code>.
 
==== Арифметика строк ====
 
Кто бы мог подумать, но строки можно складывать, умножать и, если постараться, то и делить. Естественно, что это не арифметические операции чисел, а методы со своим особенным поведением. Рассмотрим сложение, которое в строках работает как сцепление (конкатенация):
 
<source lang="ruby">boy = "Саша"
girl = "Маша"
boy + " + " + girl + " = любовь!" #=> "Саша + Маша = любовь!"</source>
 
Вот такое вот романтическое сцепление сердец!
 
Переходим к умножению. Умножают стро́ки только на целое число. Строка, которую умножают просто копируется указанное число раз. Давайте напишем речь для кукушки, чтобы она не сбилась и не накукукала нам слишком мало.
 
<source lang="ruby">years_left = 100
"Ку-ку! " * years_left
#=> "Ку-ку! Ку-ку! Ку-ку! Ку-ку! Ку-ку! Ку-ку! Ку-ку! … Ку-ку! Ку-ку! "</source>
 
Теперь за своё будущее можно не беспокоиться! Хотя нам может попасться неграмотная кукушка…
 
С делением совсем другая история. Сейчас его в языке просто нет, но этот недостаток уже ощущают многие. Смысл деления состоит в том, чтобы преобразовать строку в массив, разбив её по разделителю. Давайте преобразуем речь кукушки в массив и посмотрим, сколько же лет она нам насчитала:
 
<source lang="ruby">cuckoo_talk = "Ку-ку! Ку-ку! Ку-ку! Ку-ку! Ку-ку! Ку-ку! Ку-ку! … Ку-ку! Ку-ку! "
(cuckoo_talk / " ").size #=> 100</source>
 
В нашем примере метод <code>.size</code> считает число элементов массива, который получился в результате деления.
 
Скобки нужны для того, чтобы вызвать <code>.size</code> от результата деления, а не от <code>" "</code>.
 
Деление в примере работает также как и метод <code>.split</code>, о котором речь пойдёт чуть позже. А чтобы оно заработало у вас, необходимо добавить небольшой код в начало программы:
 
<source lang="ruby">class String
alias / :split
end</source>
 
Этот код как раз и говорит о том, что деление и <code>.split</code> — одно и тоже.
 
Деление стало нужно, когда метод <code>*</code> для массивов получил возможность работать, как <code>.join</code> (преобразовать массив в строку, расположив элементы через разделитель). В виду того, что <code>.join</code> и <code>.split</code> работают вместе точно также, как умножение и деление, то появилась идея заставить работать деление как <code>.split</code>.
 
==== Преобразование в массив или путешествие туда и обратно ====
 
Случилось так, что итераторы в строках работают настолько неуклюже, что рассмотрение их в рамках учебника будет пропущено. Следовательно, для того, чтобы задействовать механизм итераторов, мы будем преобразовывать строки в массивы. После того, как итераторы нам станут не нужны, то мы вернёмся к строкам.
 
<source lang="ruby">"Ку-ку".split('-') #=> ["Ку", "ку"]
"Ку-ку".split('y') #=> ["К", "-к"]</source>
 
Обратите внимание, что разделитель из результата исчезает.
 
За преобразование строки́ в массив отвечает метод <code>.split</code>. Ему передаётся разделитель, по которому будет происходить деление строки на элементы. В нашем случае это <code>'-'<code>. Теперь вернём всё на место. Для этого мы будем использовать метод <code>.join</code> из арсенала массивов:
 
<source lang="ruby">["Ку", "ку"].join('-') #=> "Ку-ку"
["Ку", "ку"].join(', ') #=> "Ку, ку"
["Ку", "ку"].join #=> "Куку"
["Ку", "ку"].to_s #=> "Куку"</source>
 
Кукушка кукует,<br />
строку генерит.<br />
Из строчки массив<br />
Получу через <code>.split</code>.
 
* Разделитель будет вставлен между элементами исходного массива.
* Метод <code>.join</code> вызванный без разделителя, даёт такой же результат, как и метод <code>.to_s</code>.
 
Чуть ранее мы упоминали, что можно использовать умножение вместо <code>.join</code>. Давайте посмотрим, как это выглядит:
 
<source lang="ruby">["Ку", "ку"] * '-' #=> "Ку-ку"
["Ку", "ку"] * 3 #=> ["Ку", "ку", "Ку", "ку", "Ку", "ку"]</source>
 
Если умножать массив на целое число, то будет размножение массива (прямо как умножение в строках), а не преобразование в строку.
 
==== Длина строки ====
 
Длина строки определяется точно также, как и длина массива или хеша, то есть методом <code>.size</code>:
 
<source lang="ruby">"Во дворе дрова, а в дровах трава!".size #=> 33
"Три".size #=> 3</source>
 
Следует помнить, что пробел является символом, хотя и не отображается на экране.
 
Ограничительные кавычки или апострофы в количество символов не входят! Они предназаначены лишь для того, чтобы Ruby понял, где начинается и заканчивается строка.
 
==== Получение подстрок ====
 
Получение подстрок работает точно также, как и получение подмассива. С тем лишь отличием, что нумерация идёт не по элементам, а по символам. Это логично, особенно если учесть, что для строки элементом является символ.
 
<source lang="ruby">string = "Во дворе дрова, а в дровах трава!"
string[27..-1] #=> "трава!"
string[27...-1] #=> "трава"
string[9...14] #=> "дрова"
string[9..13] #=> "дрова"</source>
 
Отрицательная нумерация тоже работает, то есть последний элемент имеет индекс <code>-1</code>, предпоследний <code>-2</code> и так далее.
 
Помните, что три точки в диапазоне дают подстроку без крайнего правого элемента. Кто-то шлагбаумом балуется!
 
Чтобы получить один единственный символ, необходимо получить подстроку длины 1.
 
<source lang="ruby">
string = "Во дворе дрова, а в дровах трава!"
string[3..3] #=> "д"
string[3] #=> 190</source>
 
Для получения подстроки или символа из строки необходимо всегда указывать диапазон. Даже если в диапазоне всего один элемент.
 
Если мы указываем не диапазон, а число, то метод <code>[]</code> выдаёт нам не символ, а его целочисленный код.
 
<source lang="ruby">string = "Во дворе дрова, а в дровах трава!"
string[3] #=> 190
string[3].chr #=> "д"</source>
<!-- не работает для UTF-8 -->
 
Для преобразования целочисленного кода обратно в символ, используется метод <code>.chr</code>.
 
==== Строка-перевёртыш ====
 
Иногда хочется перевернуть строку задом наперед. Причины могут быть разные. Например, вы ищете палиндром (число, которое можно перевернуть без ущерба для его значения). Занимается этим благородным делом метод <code>.reverse</code>.
Узнаем настоящее имя Алукарда из аниме Hellsing:
 
<source lang="ruby">"Алукард.".reverse
#=> ".дракулА"</source>
 
 
Не стоит путать метод <code>.reverse</code> для массивов с методом <code>.reverse</code> для строк. В массивах меняется порядок элементов, а в строках — символов.
 
==== Меняю шило на мыло! ====
 
Для того, чтобы заменить <code>"шило"</code> на <code>"мыло"</code> используется не газета «Из рук в руки», а методы <code>.sub</code> и <code>.gsub</code>:
 
<source lang="ruby">"шило в мешке не утаишь".sub("шило", "мыло")
#=> "мыло в мешке не утаишь"</source>
 
Естественно, что менять можно не только шило и мыло, но и другие данные. Например, возраст. Девушка Ирина утверждает, что ей 18, но мы-то знем, что ей 26. Давайте восстановим истину, возможно — в ущерб своему здоровью:
 
<source lang="ruby">"Ирине 18 лет.".sub("18", "26") #=> "Ирине 26 лет."</source>
 
Заметили, что мы используем только метод <code>.sub</code>? Давайте теперь рассмотрим работу метода <code>.gsub</code> и его отличие от <code>.sub</code>. На этот раз мы будем исправлять текст, авторы которого — недоучки, забывшие про правило «Жи, Ши — пиши через 'и'»
 
<source lang="ruby">string = "жыло-было шыбко шыпящее жывотное"
string.sub("жы", "жи") #=> "жило-было шыбко шыпящее жывотное"
string.gsub("жы", "жи") #=> "жило-было шыбко шыпящее животное"
string.gsub("жы", "жи").gsub("шы", "ши") #=> "жило-было шибко шипящее животное"</source>
 
Метод <code>.sub</code> производит только одну замену, а <code>.gsub</code> — все возможные.
 
Название метода <code>.sub</code> произошло от английского «substitute» — «замена», созвучное же название метода <code>.gsub</code> отличается от него только словом «global».
 
==== Сканируем текст на ошибки. ====
 
Давайте найдем и посчитаем ошибки. Искать мы будем методом <code>.scan</code>.
 
<source lang="ruby">string = "жыло-было шыбко шыпящее жывотное"
string.scan("шы") #=> ["шы", "шы"]
string.scan("шы").size #=> 2
string.scan("жы").size #=> 2
string.scan("жы").size + string.scan("шы").size #=> 4</source>
 
Метод <code>.scan</code> находит все указанные подстроки и возвращает их в виде массива строк. В данном примере, метод <code>.size</code> считает количество элементов массива, возвращаемого <code>.scan</code>.
 
Ужас, в одном предложении целых четыре ошибки. Будем отчислять!
 
{{Начало цитаты}}
Нашел ошибку метод <code>.scan</code>,<br />
В массив её запомнил.<br />
Учителям он свыше дан!<br />
Зачем его я вспомнил?!
{{Конец цитаты}}
 
==== Правила работы со строками. ====
 
Правила — это образцы к которым можно примерять строки. Правила обладают своим собственным языком, который позволяет описывать одну, две, сотню и вообще любое количество строк. Это своеобразная упаковка для множества строк в одну компактную запись.
 
Правила в Ruby ограничиваются символами <code>/</code> (косая черта). Примеры правил:
 
<source lang="ruby">
/(жы|шы)/
/\w+@[\w\.]+\w+/i</source>
 
Страшно? А зря На самом деле работа с правилами очень проста. Главное привыкнуть и попрактиковаться.
 
Составные части правил:
 
;Символьные классы: Перечисление символов, которые может содержать строка.
;Квантификаторы: Количество символов.
;Альтернативы: Пречисление всевозможных вариантов.
;Группировки: Возможность выделить несколько групп, которые могут обрабатываться отдельно.
;Модификаторы: Изменение поведения правила. Например, игнорирование регистра символов.
 
Правила в рамках учебника будут описаны очень сжато. Многие тонкости освещены не будут, поэтому для освоения «фигур высшего пилотажа» необходимо прочитать специализированную литературу. Например, [http://www.books.ru/shop/books/82357 книгу «Регулярные выражения»]}}
 
===== Символьный класс. =====
 
Символьный класс — просто конечный набор символов. Он ограничивается квадратными скобками и содержит перечисление символов, которые можно вместо него подставить. Заменяется он всего на один символ, входящий в этот класс. Примеры символьных классов:
 
<source lang="ruby">
/[абвгде]/ #=> простое перечисление символов
/[а-яА-Я]/ #=> все русские буквы
/[0-9a-z]/ #=> цифры и строчная латиница
/[^0-9]/ #=> все символы, кроме цифр</source>
 
* Можно использовать <code>-</code> (дефис) для указания диапазонов символов.
* Если первый символ класса (идущий сразу после открывающейся квардратной скобки) — <code>^</code> (циркумфлекс), то это означает символ, который отсутствует в данном классе.
* Некоторые популярные классы имеют короткую запись.
 
{| class="standard"
|+Короткие записи популярных символьных классов
|-
!Короткая<br />запись || Полная<br />запись || Описание
|-
|<code>\s</code>||<code>[\f\t\n\r]</code> || Пробельный символ
|-
|<code>\S</code>||<code>[^\f\t\n\r]</code> || Любой символ, кроме пробельного
|-
|<code>\d</code>||<code>[0-9]</code> || Цифра
|-
|<code>\D</code>||<code>[^0-9]</code> || Любой символ, кроме цифры
|-
|<code>\w</code>||<code>[a-zA-Z0-9]</code> || Латиница или цифра
|-
|<code>\W</code>||<code>[^a-zA-Z0-9]</code> || Любой символ, кроме латиницы или цифры
|-
|<code>.</code> ||<code>[^\n\r]</code> || Любой символ, кроме перевода строки
|-
|<code>\b</code>||<code></code> || Граница слова
|-
|<code>\B</code>||<code></code> || Не граница слова
|-
|<code>\A</code>||<code></code> || Начало строки
|-
|<code>\Z</code>||<code></code> || Конец строки
|}
 
Взгляните на примеры правил! Правда, они стали понятней? По крайней мере второе…
 
===== Квантификатор =====
 
Показывает, сколько раз может повторяться предыдущий символ, группа, альтернатива, etc. Квантификатор ограничивается фигурными скобками.
 
Примеры квантификаторов:
 
<source lang="ruby">/\w{3}/ #=> три латинских буквы или цифры
/\d{1, 3}/ #=> одна, две или три цифры
/[а-яА-Я]{3, }/ #=> русское слово длинной три символа и больше</source>
 
* Квантификатор с одним параметром называется ''точным'' и указывает точное количество повторений.
* Квантификатор с двумя агрументами называется ''конечным'' и указывает конечный диапазон, в котором варьируется количество повторений.
* Квантификатор без второго параметра (но с запятой) называется ''бесконечным'' и ограничивает количество повторений лишь снизу.
* Некоторые популярные квантификаторы имеют короткую запись.
 
{| class="standard"
|+ Короткие записи популярных квантификаторов
|-
!Короткая<br/>запись||Полная<br/>запись||Описание
|-
|<code>*</code>||<code>{0, }</code> ||Любое количество
|-
|<code>+</code>||<code>{1, }</code> ||Один и более
|-
|<code>?</code>||<code>{0, 1}</code>||Есть или нет
|}
 
Снова посмотрите на примеры правил. Теперь вам они понятны? Если нет, то перечитайте две предыдущие главы — в них основа правил.
 
===== Альтернатива =====
 
Альтернатива нужна, когда необходимо объединить несколько правил в одно. При этом совпадение засчитывается, когда есть совпадение хотя бы с одним правилом. Желательно альтернативу заключать внутрь группировки (круглые скобки). Правила, входящие в альтернативу, разделяются <code>|</code> (вертикальной чертой, которая и является альтернативой). Примеры альтернатив:
 
<source lang="ruby">/(жы|шы)/ #=> или "жы", или "шы"
/(\w+|[а-яА-Я]+)/ #=> или слово на латинице, или русское</source>
 
Вместо альтернативы можно задействовать логические итераторы <code>.any?</code> и <code>.all?</code> внутри <code>.inject</code>. Получается более гибкая конструкция.
 
В данном примере продемонстрирована альтернатива с группировкой. В принципе альтернатива может существовать и без неё, но так возникает меньше ошибок у начинающих.
 
===== Группировка =====
 
Группировка используется, когда необходимо обрабатывать результат частями. Например, при обработке ссылок в [[w:HTML|HTML]]-документе удобно отдельно обрабатывать текст ссылки и [[w:URL|URL]]. Группировка также как и альтернатива, заключается в круглые скобки. Более того, альтернатива обрабатывается как группировка. Доступ к результату совпадения каждой группировки осуществляется посредством специальных переменных <code>$1</code>, <code>$2</code>, …, <code>$9</code>. Подробнее группировки будут рассмотрены в подразделе «[[#Правильная замена|Правильная замена]]». Пример использования группировки:
 
<source lang="ruby">"2+7*3".gsub(/(\d+)\*(\d+)/){ $1.to_i * $2.to_i } #=> "2+21"</source>
 
Почти калькулятор!
 
Существует много видов группировок. Например, <code>(?:…)</code> — группировка без сохранения результата в «долларовую переменную» или <code>(?!…)</code> — негативная группировка. В любом случае они ограничиваются парой круглых скобок.
 
===== Фиксирующая директива =====
 
Фиксирующие директивы — это символы, которые привязывают правило к некоторому признаку. Например, к концу или началу строки.
 
<source lang="ruby">/^\d+/ #=> строка начинается с числа
/\w+$/ #=> последнее слово на латинице или число
/^$/ #=> пустая строка</source>
 
Насколько видно из примеров,
 
* <code>^</code> — привязка к началу строки,
* <code>$</code> — привязка к концу строки.
 
Фиксирующих директив гораздо больше двух. Об остальных читайте в специализированной литературе.
 
===== Модификатор =====
 
Модификатор предназначен для изменения поведения правила. Он размещается сразу же после правила (после последней наклонной черты). Пример использования модификатора:
 
<source lang="ruby">/(hello|world)/i #=> или "hello", или "world". Причём независимо от регистра
/\s+/mix #=> несколько подряд идущих пробельных символов</source>
 
Бывают следующие модификаторы:
 
* '''m'''ultiline — перенос строки считается простым символом,
* '''i'''gnorcase — поиск без учёта регистра,
* e'''x'''tended — игнорировать пробельные символы.
 
Игнорирование регистра работает только для латиницы.
 
* Можно применять любое количество модификаторов и в любом порядке.
* Обратите внимание, что модификаторы образуют слово ''mix''.
 
Теперь можно не бояться страшных правил.
 
==== Правильное разбиение ====
 
Разбиение называется «правильным» тогда, когда в качестве аргумента метода <code>.split</code> используется правило. Например, можно разбить текст по знакам препинания. Для этого необходимо выполнить следующий код.
 
<source lang="ruby">"Раз, два, три!".split(/[, \.?!]+/) #=> ["Раз", "два", "три"]</source>
 
Обратите внимание, что в результирующем массиве знаки препинания отсутствуют.
 
==== Правильная замена ====
 
С правильной заменой не всё так просто. Дело в том, что методы <code>.sub</code> и <code>.gsub</code> совместно с правилами становятся итераторами, которые последовательно обрабатывают каждое совпадение с правилом. Чтобы это увидеть в действии, давайте решим задачу исправления ошибок:
 
<source lang="ruby">"Жыло-было шыбко шыпящее жывотное".gsub(/(ж|ш)ы/){ $1 + "и" }
#=> "Жыло-было шибко шипящее животное"</source>
 
Опаньки, а первое слово не исправилось! Видимо дело в том, что слово <code>Жыло</code> начинается с прописной буквы. Сейчас исправим:
 
<source lang="ruby">"Жыло-было шыбко шыпящее жывотное".gsub(/(Ж|Ш|ж|ш)ы/){ $1 + "и" }
#=> "Жило-было шибко шипящее животное"</source>
 
Вот, теперь гораздо лучше. Как мы этого добились? Давайте разберёмся. Начнём с регулярного выражения:
 
<source lang="ruby">/(Ж|Ш|ж|ш)ы/</source>
 
Оно состоит из двух частей:
 
* альтернативы с группировкой — <code>(Ж|Ш|ж|ш)</code>,
* символа — <code>ы</code>.
 
В альтернативе мы указали буквы с которых начинается неправильный слог. Символ просто добавляется к букве из альтернативы.
 
Зачем была использована группировка? Для пояснения причины, рассмотрим код в фигурных скобках:
 
<source lang="ruby">{ $1 + "и" }</source>
 
Вот для того, чтобы можно было использовать переменную <code>$1</code> (результат первой группировки) мы и задействовали группировку. В данном случае, в <code>$1</code> сохраняется первая буква слога, которая в результате исправления оШЫбки не меняется.
 
* Для того, чтобы получить доступ к результату первой группировки, надо обратиться к переменной <code>$1</code> (один доллар), ко второй — <code>$2</code> (два доллара) и так далее до переменной <code>$9</code> (девять долларов).
* Переменные <code>$1</code> — <code>$9</code> заимствованы из языка Perl.
 
Можно ли было решить эту же задачу иначе? Конечно можно!
 
<source lang="ruby">"Жыло-было шыбко шыпящее жывотное".gsub(/([ЖШжш])ы/){ $1 + "и" }
#=> "Жило-было шибко шипящее животное"</source>
 
На этот раз мы просто задействовали символьный класс вместо альтернативы, который описывает первую букву слога с оШЫбкой.
 
Есть ещё пару интересных моментов, которые вам необходимо знать. Во время предыдущего примера вас могли посетить следующие вопрос: а как получить весь текст, который совпал с правилом? Неужели необходимо делать всеобщую группировку?
 
Ответ на этот вопрос одназначный — нет! Достаточно придумать название переменной (которая будет содержать совпавший текст) и правильно описать внутри ушек:
 
<source lang="ruby">"Раз, два, три!".gsub(/[а-я]+/){ |word| word.reverse }
#=> "заР, авд, ирт!"</source>
Вообще-то в слове Раз переворачиваются только 2 последние буквы.
 
==== Правильный поиск ====
 
Вот здесь метод <code>.scan</code> может развернуться в полную силу. Хотите получить массив всех русских слов в тексте? Запросто:
 
<source lang="ruby">"Раз, два, три!".scan(/[А-Яа-я]+/) #=> ["Раз", "два", "три"]</source>
 
Хотите получить все знаки препинания? Нет ничего проще:
 
<source lang="ruby">"Раз, два, три!".scan(/[, \.;:!]+/) #=> [", ", ", ", "!"]</source>
 
Если необходимо в метод <code>.scan</code> передавать правило с группировкой, то желательно использовать группировку без сохранения результата, то есть <code>(?:…)</code>. Иначе результатом метода <code>.scan</code> будет совпадение с группировкой, а не с правилом.
 
Например, ниже записана программа, которая занимается поиском адресов электронной почты.
 
<source lang="ruby">string = "495-506-13 56 nata@rambler.ru(34) 1.5.1232 12.14.56 31.декабря.9999"
string.scan(/(?:[-a-z_\.])+@(?:[-a-z])*(?:\.[a-z]{2,4})+/) #=> ["nata@rambler.ru"]</source>
 
Выполните её, посмотрите результат, а потом замените любую из группировок <code>(?:…)</code> на <code>(…)</code> и снова взгляните на результат.
 
Ну со <code>.scan</code> должно быть всё понятно. А вот то, что метод <code>[]</code> начинает тоже правильно искать — пока нет.
 
<source lang="ruby">"Раз, два, три!"[/[А-Яа-я]+/] #=> "Раз"</source>
 
Если методу <code>[]</code> передать в качестве параметра правило, то он вернёт либо совпадение с правилом, либо <code>nil</code>.
 
Очень полезно использовать <code>[]</code> в ситуациях, когда надо узнать ответ на вопрос «есть хотя бы одна подстрока, которая удовлетворяет правилу?» или получить первое (или единственное) совпадение с правилом.
 
Существует древнее поверье, что если использовать одно и тоже правило для <code>.scan</code> и <code>.split</code>, то получаются две части текста, из которых реально получить исходный.
 
<source lang="ruby">Text.scan(rule) + Text.split(rule) = Text</source>
 
Это значит, что если метод <code>.split</code> использует правило, описывающие все знаки припинания, то результатом будет текст без знаков припинания. А вот если это же правило будет использовать метод <code>.scan</code>, то в результате мы получим все знаки препинания без текста.
 
Рекомендуется использовать метод <code>[]</code> вместо метода <code>=~</code> (заимствованного из Perl), так как <code>[]</code> более функционален.
 
==== Жадность ====
 
Речь пойдёт о жадности среди квантификаторов. Возьмем некоторый квантификатор <code>{n, m}</code> и посмотрим как он работает.
 
{{info|Нежадные квантификаторы иногда называют щедрыми.}}
 
Сперва он начинает искать последовательность длины <code>m</code> (вот так щедрость), и если правило не срабатывает, он начинает уменьшать длинну последовательности вплоть до <code>n</code>. Так работают обычные (щедрые) кванторы.
 
Но иногда щедрые кванторы не могут справиться с задачей. Например, в файле на языке HTML мы осуществляем поиск ссылок (тег <code>&lt;a&gt;</code>). Правило с щедрым квантором найдёт начало первой ссылки и конец последней. Весь остальной текст оно примет за текст ссылки. Понятно, что работать верно оно будет только в двух случаях: когда в тексте нет ссылок или когда ссылка только одна.
 
Для решения вышеописанной проблемы и был придуман так называемый жадный квантификатор. От щедрого он отличается обратным ходом обработки, то есть длину последовательности он не уменьшает от <code>m</code> к <code>n</code>, а наоборот, увеличивает от <code>n</code> до <code>m</code>. Научить жадности квантификатор можно знаком вопроса <code>?</code> после любого (щедрого) квантификатора.
 
<source lang="ruby">"Раз, два, три!".scan(/[А-Яа-я]+?/)
#=> ["Р", "а", "з", "д", "в", "а", "т", "р", "и"]
"Жуй жвачку, жывотное!".gsub(/([жЖшШ]??)ы/){ $1 + 'и' }
#=> "Жуй жвачку, животное!"</source>
 
{{info|С рождения квантификаторы щедры. Жадность — обретаемый признак.}}
 
{{info|К сожалению, здесь авторы "учебника" все перепутали. На самом деле, жадный квантификатор называется жадным (или - максимальным) потому, что он пытается забрать все себе, а щедрый (минимальный) - стремится отдать все другим. И потому с рождения квантификаторы жадны, а щедрость — обретаемый признак.
 
Всем сомневающимся - читать [http://www.books.ru/shop/books/82357 книгу Джона Фридла «Регулярные выражения»]}}
 
=== Хитрости ===
 
==== Перенос по словам ====
 
Несколько лет назад (ещё при жизни http://ruby-forum.ru) решали мы интересную задачу: как реализовать автоматический перенос на новую строку (wrap). Для тех, кто не застал те времена, уточню задание: дан текст, необходимо, вставить переносы таким образом, чтобы каждая из полученных строк была меньше <code>n</code> (для определённости <code>n = 80</code>). Недавно я осознал, что не могу решить эту задачу тем способом, который был нами тогда найден. Я его просто не помнил… Решение нашлось быстро, достаточно было вспомнить, что на английском языке эта задача именуется коротким и ёмким словом wrap.
 
<source lang="ruby">class String
def wrap(col = 80)
gsub(/(.{1,#{col}})( +|$\n?)|(.{1,#{col}})/, "\\1\\3\n")
end
end</source>
 
Немного о структуре кода. Метод <code>.wrap</code> реализован для экземпляров класса <code>String</code>. Также стоит обратить внимание на то, что внутри правила (регулярного выражения) возможна «вставка» (как в «рабочих строках»). Используется сей метод следующим образом:
 
<source lang="ruby">p "wrapping text with regular expressions".wrap(10)
#=> "wrapping\ntext with\nregular\nexpression\ns\n"</source>
 
Теперь давайте разберёмся с правилом. Чтобы не смущать неокрепшие умы, заменим вставку на 80. Правило станет короче и менее страшным.
 
<source lang="ruby">(.{1, 80})( +|$\n?)|(.{1, 80})</source>
 
Очевидно, что оно состоит из четырёх частей:
 
* <code>(.{1, 80})</code> — строка длиной от 1 до 80 символов (любых). Результат группировки записывается в <code>$1</code> (один доллар) или <code>"\\1"</code>.
* <code>( +|$\n?)</code> — пробелы или конец строки. Результат группировки записывается в <code>$2</code> (два доллара) или <code>"\\2"</code>. Обратите внимание на запись <code>$\n?</code>, которая означает «конец строки (<code>$</code>), после которого может идти перенос (<code>\n</code>)». Обратите внимание, что <code>$2</code> мы не используем и поэтому можно использовать <code>(?:)</code> (группировку без сохранения результата).
* <code>|</code> — или.
* <code>(.{1, 80})</code> — строка длиной от 1 до 80 символов (любых). Результат группировки записывается в <code>$3</code> (три доллара) или <code>"\\3"</code>.
 
В результате работы этого правила произойдёт сопоставление с группировками 1 и 2 или 3. В первом случае будет обрабатываться строка, слова в которой по длине не превышают 80. Во втором случае строка будет принудительно усечена до 80 символов. Другими словами, мы пытаемся сделать перенос по словам, но если у нас не получается, то мы будем делать перенос так, как у нас получится.
 
Представленное решение не идеально. В частности, слова с дефисом хорошо бы переносить именно по дефису (при этом оставляя его на первой строке). Про остальные изыски (перенос по слогам и так далее) вы можете догадаться самостоятельно. Эта задача может решаться бесконечно, предусматривая всё большее количество различных вариантов. Плюс ко всему, возможны комбинации с другими задачами (найти длину самого длинного слова и осуществить перенос по этой длине).
 
Источник (англоязычный): http://macromates.com/blog/archives/2006/06/28/wrapping-text-with-regular-expressions/
 
==== Методы преобразования к строке ====
 
Ruby сам преобразует типы для некоторых простых операций. Например, при включении строки в другую он воспользуется имеющимся у обьекта методом <code>.to_s</code>:
 
<source lang="ruby">class Container
def to_s
"контейнер"
end
end
 
cont = Container.new
 
p "Это #{cont}" #=> "Это контейнер"</source>
 
Если нужно, чтобы ваши обьекты упорядочивались и сравнивались с обычными строками, следует применять примесь <code>Comparable</code> и единственный специальный метод <code>to_str</code>. Наличие этого метода у вашего объекта — знак для Ruby, что для сравнения следует применять не встроенный в <code>String</code> метод, а ваш.
 
<source lang="ruby">class Container
include Comparable
def to_str
"контейнер"
end
 
def to_s
"контейнер"
end
 
def <=>(other)
to_s <=> other.to_s
end
end
 
cont = Container.new
 
"контейнер" == cont #=> true</source>
 
=== Задачи ===
 
# Дана строка слов, разделёных пробелами. Вывести длиннейшее слово.
# Дана строка, содержащая кириллицу, латиницу и цифры. Вывести все слова, длина которых равна средней.
# Найти в строке первое целиком кириллическое слово.
# Дан текст (строка с переносами). Найти все слова, содержащие лишь три буквы «о».
#* Только для русских слов.
#* Для французских и русских слов.
#* Для любого регистра буквы «о».
# Найти в тексте время в формате «часы:минуты:секунды».
# Найти все слова без повторяющихся букв (например, «Лисп» или «Ruby», но не «Паскаль» или «Java»).
#* Только для русскоязычных слов.
#* Не учитывайте цифры в словах.
# Найти в тексте слова́, содержащие две прописные буквы, и исправить.
#* Решите задачу для слов и в кириллице, и в латинице.
# Найти в тексте даты формата «день.месяц.год».
#* Найдите дату, где день ограничен числом 31, а месяц 12. Год ограничивайте четырёхзначными числами.
#* Распознавайте месяц в виде «31.марта.2001».
# Дан текст. Найдите все URL адреса и вычлените из них ссылку на корневую страницу сайта (например, из http://ru.wikibooks.org/wiki/Ruby сделайте http://ru.wikibooks.org).
[[Категория:Ruby|Подробнее о строках]]