Поиск

Дополнительная информация о регулярных выражениях

Выше мы рассмотрели основные способы обработки текста, находящегося в переменной $_, с помощью оператора подстановки. Теперь вас ждет новая порция информации по функциональным возможностям регулярных выражений. Эффективное использование регулярных выражений предполагает возможность работы не только с $_, но и с другими переменными, использование сложных подстановок, а также применение функций Perl, имеющих отношение к регулярным выражениям.

Работа с другими переменными

В предыдущей программе введенная пользователем масса хранилась в переменной $_, поэтому все поиски по шаблону и подстановки выполнялись с этой переменной. Переменная $ — не самое удобное место для хранения массы тела. Во-первых, это не очень понятно для начинающих программистов, а во-вторых значение переменной $_ может быть неожиданно изменено в другом месте программы.

Вообще длительное хранение чего либо в $_— это игра с огнем, поскольку многие из операторов Perl по умолчанию используют эту переменную и модифицируют ее. В Perl $_ считается переменной общего пользования и длительное хранение в ней каких-либо данных, как правило, приводит к ошибкам. Изучив материал 8-го занятия, "Функции", вы сами в этом убедитесь.

В программе, приведенной в листинге 6.1, лучше ввести новую переменную $weight. Для выполнения с ней операций поиска и замены необходимо "привязать" эту переменную к соответствующим операторам. Для этого используется оператор привязки =":

Оператор =" не производит никакого присваивания, он просто определяет, что оператор справа действует на переменную слева. Значение всего выражения такое же, как и при использовании переменной $_, как можно видеть из примера:

Модификаторы и многократный поиск

До сих пор наши регулярные выражения были чувствительны к регистру. Это значит, что символы верхнего и нижнего регистров воспринимались ими как разные. Для поиска слов без учета регистра букв можно использовать шаблоны, подобные этим:

Как видите, это довольно громоздкий способ, часто приводящий к ошибкам из-за неправильного набора пар букв. Существует гораздо лучший способ. В операторах подстановки (s///) или поиска по шаблону (га//) предусмотрен режим, в котором не учитывается регистр букв в искомых словах. Для этого после шаблона нужно поместить суффикс i, например:

Этот оператор найдет слово Macbeth в прописном, строчном или каком-нибудь иномсмешанномварианте(MaCbEtH).

Кроме суффикса i, в операторах поиска и подстановки можно использовать модификатор д, который задает режим глобального поиска. Поиск (или подстановка) при этом будут выполняться многократно по всей строке: сначала находится первое слева совпадение и выполняется первая подстановка, а затем поиск и замена продолжаются до конца строки.

В контексте списка оператор поиска с модификатором g возвращает список, элементы которого соответствуют группам регулярного выражения, например:

Шаблон состоит из символа-разделителя (любого не текстового символа), буквы f и трех любых текстовых символов. Буква f и три символа объединены в группу с помощью скобок. После вычисления выражения в массиве @F будет содержаться четыре элемента: fish, frog, fred и foul.

В скалярном контексте оператор поиска с модификатором д проходит всю строку и при каждом совпадении возвращает истинное значение. Если больше совпадений не найдено, то возвращается ложное значение. Вот пример:

Здесь оператор поиска (//) с модификатором g находится в скалярном контексте, поскольку он используется в условном выражении while. Шаблон предназначен для поиска текстового символа. Цикл while продолжается (и переменная $letter увеличивается) до тех пор, пока оператор поиска не возвращает ложное значение. После окончания цикла переменная $letters будет иметь значение 11.

Значительно более эффективный метод подсчета символов будет рассмотрен на 9-м занятии, "Дополнительные функции и операторы".
Обратные ссылки

Если в регулярных выражениях Perl используются скобки, части искомой строки, соответствующие фрагментам в скобках, запоминаются в специальных переменных (первый фрагмент в скобках), (второй), , и т.д. Вот пример:

Этот шаблон служит для поиска правильно отформатированных телефонных номеров, принятых в США и Канаде, например таких как 800-555-1212. Каждая порция номера запоминается в специальных переменных , и . Эти переменные могут быть использованы в программе, например:

Кроме программы, специальные переменные , и т.д. могут использоваться в строке замены оператора подстановки, например:

Но будьте внимательны, эти переменные модифицируются при каждом успешном поиске, независимо от использования в регулярном выражении скобок. Кроме того, значения этих переменных устанавливаются тогда и только тогда, когда строка полностью соответствует шаблону. Приняв это во внимание, посмотрите на пример:

В этом примере переменная используется без проверки успешности поиска по шаблону. В случае неудачного поиска это может привести к ошибке в программе.

Новая функция: grep

Поиск в массиве по шаблону — одна из наиболее распространенных операций Perl. Например, вы считываете весь файл в массив и хотите знать, в каких строках файла встречается определенное слово. Как раз для подобных ситуаций в Perl имеется функция grep. Вот ее синтаксис:

Функция grep проходит каждый элемент списка и выполняет для него указанное выражение или блок. Внутри выражения или блока в качестве очередного элемента списка выступает переменная $_. Если выражение истинно, данный элемент возвращается функцией grep. Ниже приведен пример:

Здесь каждый элемент массива @dogs поочередно присваивается переменной $_, затем в этой переменной производится поиск по шаблону /hound/. Каждый из элементов, для которого это выражение истинно, возвращается функцией grep и помещается в массив @hounds.

Существует два важных момента. Первый заключается в том, что переменная $_ ссылается на реальный элемент списка и модификация $_ изменяет значение этого элемента, например:

После выполнения этого кода массив @hounds будет содержать элементы greyhounds и bloodhounds (обратите внимание на s в конце этих слов). Исходный массив @dogs также изменяется из-за изменения значения переменной $_. Теперь в нем будут содержаться элементы greyhounds, bloodhounds, terrier, mutt и chihuahua.

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

Функция grep получила свое имя от команды UNIX, используемой для поиска по шаблону в файлах. Это настолько полезная команда, что ее название стало именем нарицательным в мире UNIX. Для представителей этого мира выражение "grep-нуть книгу" — означает пролистать книгу в поисках нужного материала.

Родственная grep функция mар имеет аналогичный синтаксис. Отличие между ними состоит в том, что тар возвращает значение блока или выражения, а не значение переменной $_. С помощью функции mар из одного массива можно легко образовать другой, например:

В этом примере каждый элемент массива @input, передаваемый в блок как $_, разбивается по словам функцией split. В качестве символа-разделителя используется пробел. Это означает, что каждый элемент массива @input преобразуется в список слов, которые помещаются в массив @words.