Регулярные выражения
Как вы убедились, основной вариант применения команды grep легко усвоить. Теперь пришло время рассмотреть основы построения регулярных выражений, которые позволят вам выполнять более сложный поиск. Как упоминалось ранее в этой главе, регулярные выражения применяются в системе Linux и многих языках программирования с открытым исходным кодом. Вы можете использовать их в редакторе vi и в скриптах на языке Perl, применяя одни и те же принципы, общие для регулярных выражений, где бы они ни появлялись.
При обработке регулярных выражений определенные символы интерпретируются особым образом. В табл. 2.15 приведены наиболее часто используемые в регулярных выражениях символы.
Таблица 2.15
| Символ | Описание |
|---|---|
| ^ | Привязка к началу строки |
| $ | Привязка к концу строки |
| . | Любой одиночный символ |
| [] | В квадратных скобках содержится диапазон символов, с любым из них возможно совпадение, например, диапазон символов a-e или инвертированный диапазон, перед которым стоит символ ^ |
Если вы хотите использовать любые из перечисленных символов как "обычные", поставьте перед ними символ \. Например, если нужно найти символ $, просто введите \$.
Есть также несколько полезных специальных проверочных шаблонов, которые могут указываться в квадратных скобках (табл. 2.16).
Таблица 2.16
| Проверочный шаблон | Описание |
|---|---|
| [:alnum:] | Буквенно-цифровые символы |
| [:alpha:] | Буквы |
| [:ascii:] | Символы таблицы ASCII |
| [:blank:] | Пробел или табуляция |
| [:cntrl:] | Управляющие символы ASCII |
| [:digit:] | Цифры |
| [:graph:] | Неуправляющие и непробельные символы |
| [:lower:] | Строчные буквы |
| [:print:] | Печатные символы |
| [:punct:] | Знаки пунктуации |
| [:space:] | Пробельные символы, включая вертикальную табуляцию |
| [:upper:] | Прописные буквы |
| [:xdigit:] | Шестнадцатиричные цифры |
Кроме того, если задана опция =E для расширенного соответствия, за регулярным выражением могут следовать и другие символы, управляющие выполнением проверки на соответствие шаблону (табл. 2.17). В команде grep перед этими символами необходимо вводить символ \.
Таблица 2.17
| Опция | Описание |
|---|---|
| ? | Совпадение не обязательно, но возможно не более одного раза |
| * | Совпадения может не быть, оно может быть однократным или многократным |
| + | Совпадение должно быть однократным или многократным |
| {n} | Совпадение должно быть n раз |
| {n, } | Совпадение должно быть nраз и больше |
| {n, m} | Совпадение должно быть от n до mраз включительно |
Все это выглядит немного запутанно, но если осваивать все возможности постепенно, то вы увидите, что все не так сложно, как кажется на первый взгляд. Самый легкий способ понять регулярные выражения - просто попробовать применить несколько.
1. Начнем с поиска строк, заканчивающихся буквой "е". Возможно, вы уже догадались, что нужно использовать специальный символ $:
$ grep e$ words2.txt
Art thou not, fatal vision, sensible
I see thee yet, in form as palpable
Nature seems dead, and wicked dreams abuse
$
Как видите, найдены строки, заканчивающиеся буквой "е".
2. Теперь найдите трехбуквенные слова, начинающиеся с символов "Th". В данном случае вам понадобится шаблон [[:space:]] для ограничения длины слова и . для единственного дополнительного символа.
$ grep Th.[[:space:]] words 2.txt
The handle toward my hand? Come, let me clutch thee.
The curtain'd sleep; witchcraft celebrates
Thy very stones prate of my whereabout,
$
3. В заключение примените расширенный режим поиска в команде grep для обнаружения слов из строчных букв длиной ровно 10 символов. Для этого задайте диапазон совпадающих символов от а до z и 10 повторяющихся совпадений.
$ grep -Е [a-z]\{10\} words2.txt
Proceeding from the heat-oppressed brain?
And such an instrument I was to use.
The curtain'd sleep; witchcraft celebrates
hy very stones prate of my whereabout,
$
Приведенные примеры лишь коснулись наиболее важных компонентов регулярных выражений. Как и для большинства составных частей ОС Linux, существует множество дополнительной документации помимо этой книги, которая поможет вам узнать еще больше подробностей, но лучший способ изучения регулярных выражений - экспериментировать с ними.
Выполнение команд
При написании сценариев вам часто требуется перехватить результат выполнения команды для использования его в сценарии командной оболочки; т.е. вы хотите выполнить команду и поместить ее вывод в переменную.
Сделать это можно с помощью синтаксической конструкции $(команда), показанной ранее в примере с командой set. Существует устаревший вариант подстановки команды `команда`, который все еще широко распространен.
Примечание
В более раннем варианте конструкции применяется обратный апостроф или обратная кавычка (`), а не обычный апостроф ('), который мы использовали раньше в командной оболочке для экранирования (защиты от подстановки переменных). В сценариях оболочки применяйте этот вариант, только если вы хотите добиться высокой степени переносимости сценариев.
Во всех современных сценариях следует применять конструкцию выполнения или подстановки команды$(команда), которая введена для того, чтобы избавиться от довольно сложных правил использования символов $, ' и \ внутри команды, заключенной в обратные апострофы. Если применяется обратный апостроф внутри конструкции `...` , его необходимо экранировать символом \. Эти непонятные знаки часто заставляют программистов путаться, и иногда даже опытные специалисты в программировании средствами командной оболочки вынуждены ставить опыты для того, чтобы добиться правильного использования кавычек и апострофов в командах, заключенных в обратные апострофы.
Результат выполнения конструкции $(команда) - просто вывод команды. Имейте в виду, что это не статус возврата команды, а просто строковый вывод, показанный далее.
#!/bin/sh
echo The current directory is $PWD
echo The current users are $(who)
exit 0
Поскольку текущий каталог - это переменная окружения командной оболочки, первая строка не нуждается в применении подстановки команды. Результат выполнения программы who, напротив, нуждается в ней, если он должен стать переменной в сценарии.
Если вы хотите поместить результат в переменную, то можете просто присвоить его обычным образом:
whoisthere=$(who)
echo Swhoisthere
Возможность поместить результат выполнения команды в переменную сценария - очень мощное средство, поскольку оно облегчает использование существующих команд в сценариях и перехват результата их выполнения. Если когда-нибудь вам понадобится преобразовать набор параметров, представляющих собой вывод команды на стандартное устройство вывода, и передать их как аргументы в программу, возможно, вас порадует то, что команда xargs сможет это сделать за вас. Дополнительные подробности ищите на страницах интерактивного справочного руководства.