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

Содержимое удалено Содержимое добавлено
м ищите → ищете
Строка 1:
== Подробнее о строках ==
 
Строка  — это упорядоченная последовательность символов, которая располагается между ограничительными символами.
 
Строковый тип является самым популярным в любом языке программирования. Ведь без него невозможно написать любую программу (особенно учитывая, что любая программа  — это строка). При выводе на экран или записи в файл, любой тип данных преобразуется к строке (явно или неявно). Это значит, что в конечном итоге всё сводится к строковому типу. Кстати, и ввод данных тоже осуществляется в виде строки (и только потом преобразуется в другие типы).
 
{{info|Студенты четвёртого курса МЭТТ ГАИ поступили на подготовительные курсы в [[w:Московский государственный индустриальный университет|МГИУ]]. Там им начали преподавать основы программирования на Ruby. И одна из заданных им задач была: «Дано число, необходимо поменять порядок цифр на обратный». Задача сложная, но наши студенты об этом не знали и решили её преобразованием к строке: <code>given.to_s.reverse</code>. Преподаватели были поражены и впредь запретили им использовать преобразования к строке в своих программах. И всё потому, что это сильно упрощало решение и давало студентам огромное преимущество перед остальными слушателями курсов.}}
Строка 12:
Следует упомянуть два очень интересных момента:
 
* Cтроки — это универсальный тип данных, так как в строку можно преобразовать любой другой тип данных. Также строку можно преобразовать в любой другой тип данных (ведь изначально любой код программы — это строка).
* Cтроки очень удобно преобразовывать в массив и обратно (методы <code>.join</code> и <code>.split</code>). Поэтому работа со строками практически столь же удобная, как и с массивами.
 
Строка 22:
 
<!--{{Начало цитаты}}
Зажатые в лапках работать хотят,<br />
а строки в минутах лениво сопят.
{{Конец цитаты}}
-->
Давайте будем называть строки в апострофах «ленивыми», а строки в кавычках  — «работящими».
 
Вставка  — это хитрая конструкция, которая вставляется между ограничительными символами внутри строки. Она состоит из комбинации [[w:Октоторп|октоторпа]] и двух фигурных скобок (<code><b>#{</b> 'здесь был Вася' <b>}</b></code>). Внутри неё можно писать не только <code>'Здесь был Вася'</code>, но и любой программный код. Результат программного кода будет преобразован к строке и вставлен на место вставки.
 
Вставка жизнью заправляет:<br />
Код программный выполняет,<br />
Тихо результат считает,<br />
Вместо вставки подставляет.
 
Строка 39:
Специальный символ начинается со знака <code>\</code> ([[w:Обратная косая черта|обратная косая черта]]). Самые популярные из них: <code>\n</code> (переход на новую строку), <code>\t</code> ([[w:Табуляция|табуляция]]), <code>\\</code> (обратная косая черта) и <code>\"</code> ([[w:Кавычки|двойная кавычка]]).
 
Хотя специальный символ и пишется, как два знака, но на деле это всего один символ. Доказать это можно выполненением простенького кода: <code>"\n".size #=> 1</code>.
 
==== Для чего нужны работящие и ленивые строки? ====
Строка 140:
end</source>
 
Этот код как раз и говорит о том, что деление и <code>.split</code>  — одно и тоже.
 
Деление стало нужно, когда метод <code>*</code> для массивов получил возможность работать, как <code>.join</code> (преобразовать массив в строку, расположив элементы через разделитель). В виду того, что <code>.join</code> и <code>.split</code> работают вместе точно также, как умножение и деление, то появилась идея заставить работать деление как <code>.split</code>.
Строка 160:
["Ку", "ку"].to_s #=> "Куку"</source>
 
Кукушка кукует,<br />
строку генерит.<br />
Из строчки массив<br />
Получу через <code>.split</code>.
 
Строка 220:
==== Строка-перевёртыш ====
 
Иногда хочется перевернуть строку задом наперед. Причины могут быть разные. Например, вы ищитеищете палиндром (число, которое можно перевернуть без ущерба для его значения). Занимается этим благородным делом метод <code>.reverse</code>.
Узнаем настоящее имя Алукарда из аниме Hellsing:
 
Строка 227:
 
 
Не стоит путать метод <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 = "жыло-было шыбко шыпящее жывотное"
Строка 247:
string.gsub("жы", "жи").gsub("шы", "ши") #=> "жило-было шибко шипящее животное"</source>
 
Метод <code>.sub</code> производит только одну замену, а <code>.gsub</code>  — все возможные.
 
Название метода <code>.sub</code> произошло от английского "«substitute"» — - "«замена"», созвучное же название метода <code>.gsub</code> отличается от него только словом "«global"».
 
==== Сканируем текст на ошибки. ====
Строка 266:
 
{{Начало цитаты}}
Нашел ошибку метод <code>.scan</code>,<br />
В массив её запомнил.<br />
Учителям он свыше дан!<br />
Зачем его я вспомнил?!
{{Конец цитаты}}
Строка 274:
==== Правила работы со строками. ====
 
Правила  — это образцы к которым можно примерять строки. Правила обладают своим собственным языком, который позволяет описывать одну, две, сотню и вообще любое количество строк. Это своеобразная упаковка для множества строк в одну компактную запись.
 
Правила в Ruby ограничиваются символами <code>/</code> (косая черта). Примеры правил:
Строка 296:
===== Символьный класс. =====
 
Символьный класс  — просто конечный набор символов. Он ограничивается квадратными скобками и содержит перечисление символов, которые можно вместо него подставить. Заменяется он всего на один символ, входящий в этот класс. Примеры символьных классов:
 
<source lang="ruby">
Строка 305:
 
* Можно использовать <code>-</code> (дефис) для указания диапазонов символов.
* Если первый символ класса (идущий сразу после открывающейся квардратной скобки)  — <code>^</code> (циркумфлекс), то это означает символ, который отсутствует в данном классе.
* Некоторые популярные классы имеют короткую запись.
 
Строка 311:
|+Короткие записи популярных символьных классов
|-
!Короткая<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> || Граница слова
Строка 365:
|}
 
Снова посмотрите на примеры правил. Теперь вам они понятны? Если нет, то перечитайте две предыдущие главы  — в них основа правил.
 
===== Альтернатива =====
Строка 386:
Почти калькулятор!
 
Существует много видов группировок. Например, <code>(?:…)</code>  — группировка без сохранения результата в «долларовую переменную» или <code>(?!…)</code>  — негативная группировка. В любом случае они ограничиваются парой круглых скобок.
 
===== Фиксирующая директива =====
 
Фиксирующие директивы  — это символы, которые привязывают правило к некоторому признаку. Например, к концу или началу строки.
 
<source lang="ruby">/^\d+/ #=> строка начинается с числа
Строка 398:
Насколько видно из примеров,
 
* <code>^</code>  — привязка к началу строки,
* <code>$</code>  — привязка к концу строки.
 
Фиксирующих директив гораздо больше двух. Об остальных читайте в специализированной литературе.
Строка 412:
Бывают следующие модификаторы:
 
* <b>'''m</b>'''ultiline  — перенос строки считается простым символом,
* <b>'''i</b>'''gnorcase  — поиск без учёта регистра,
* e<b>'''x</b>'''tended  — игнорировать пробельные символы.
 
Игнорирование регистра работает только для латиницы.
Строка 449:
Оно состоит из двух частей:
 
* альтернативы с группировкой  — <code>(Ж|Ш|ж|ш)</code>,
* символа  — <code>ы</code>.
 
В альтернативе мы указали буквы с которых начинается неправильный слог. Символ просто добавляется к букве из альтернативы.
 
Зачем была использована группировка? Для пояснения причины, рассмотрим код в фигурных скобках:
Строка 460:
Вот для того, чтобы можно было использовать переменную <code>$1</code> (результат первой группировки) мы и задействовали группировку. В данном случае, в <code>$1</code> сохраняется первая буква слога, которая в результате исправления оШЫбки не меняется.
 
* Для того, чтобы получить доступ к результату первой группировки, надо обратиться к переменной <code>$1</code> (один доллар), ко второй  — <code>$2</code> (два доллара) и так далее до переменной <code>$9</code> (девять долларов).
* Переменные <code>$1</code>  — <code>$9</code> заимствованы из языка Perl.
 
Можно ли было решить эту же задачу иначе? Конечно можно!
Строка 472:
Есть ещё пару интересных моментов, которые вам необходимо знать. Во время предыдущего примера вас могли посетить следующие вопрос: а как получить весь текст, который совпал с правилом? Неужели необходимо делать всеобщую группировку?
 
Ответ на этот вопрос одназначный  — нет! Достаточно придумать название переменной (которая будет содержать совпавший текст) и правильно описать внутри ушек:
 
<source lang="ruby">"Раз, два, три!".gsub(/[а-я]+/){ |word| word.reverse }
Строка 496:
Выполните её, посмотрите результат, а потом замените любую из группировок <code>(?:…)</code> на <code>(…)</code> и снова взгляните на результат.
 
Ну со <code>.scan</code> должно быть всё понятно. А вот то, что метод <code>[]</code> начинает тоже правильно искать  — пока нет.
 
<source lang="ruby">"Раз, два, три!"[/[А-Яа-я]+/] #=> "Раз"</source>
Строка 554:
Очевидно, что оно состоит из четырёх частей:
 
* <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 символов. Другими словами, мы пытаемся сделать перенос по словам, но если у нас не получается, то мы будем делать перенос так, как у нас получится.
Строка 579:
p "Это #{cont}" #=> "Это контейнер"</source>
 
Если нужно, чтобы ваши обьекты упорядочивались и сравнивались с обычными строками, следует применять примесь <code>Comparable</code> и единственный специальный метод <code>to_str</code>. Наличие этого метода у вашего объекта  — знак для Ruby, что для сравнения следует применять не встроенный в <code>String</code> метод, а ваш.
 
<source lang="ruby">class Container