b8c4c21f

Использование шаблонов


Шаблоны используются в нескольких конструкциях shell. Главное место их применения - командная строка. Если оболочка "видит" в командной строке шаблон, она немедленно заменяет его списком файлов, имена которых ему соответствуют. Команда, которая затем вызывается, получает в качестве параметров список файлов уже без всяких шаблонов, как если бы этот список пользователь ввел вручную. Эта способность командного интерпретатора называется генерацией имен файлов:

[methody@localhost methody]$ ls .bash* .bash_history .bash_logout .bash_profile .bashrc [methody@localhost methody]$ /bin/e* /bin/ed /bin/egrep /bin/ex [methody@localhost methody]$ ls *a* -filename-with- [methody@localhost methody]$ ls -dF *[ao]* Documents/ examples/ loop to.sort*

Пример 8.7. Использование шаблона в командной строке (html, txt)

Мефодий, как это случается с новичками, немедленно натолкнулся на несколько "подводных камней", неизбежных в ситуации, когда конечный результат неизвестен. Только первая команда сработала не вопреки его ожиданиям: шаблон ".bash*" был превращен командной оболочкой в список файлов, начинающихся на .bash, этот список получила в качестве параметров командной строки ls, после чего честно его вывела. С "/bin/e*" Мефодию повезло - этот шаблон превратился в список файлов из каталога /bin, начинающихся на "e", и первым файлом в списке оказалась безобидная утилита /bin/echo. Поскольку в командной строке ничего, кроме шаблона, не было, именно строка /bin/echo была воспринята оболочкой в качестве команды1), которой (в качестве параметров) были переданы остальные элементы списка - /bin/ed, /bin/egrep и /bin/ex.

Что же касается ls *a*, то, по расчетам Мефодия, эта команда должна была выдать список файлов в текущем каталоге, имя которых содержит "a". Вместо этого на экран вывелось имя файла из подкаталога examples... Впрочем, никакой черной магии тут нет. Во-первых, имена файлов вида ".bash*" хотя и содержат "a", но начинаются с точки, и, стало быть, считаются скрытыми. Скрытые файлы попадают в результат генерации имен только если точка в начале указана явно (как в первой команде примера). Поэтому по шаблону "*a*" в домашнем каталоге Мефодия bash нашел только подкаталог с именем examples - его-то он и передал в качестве параметра утилите ls. Что было выведено на экран в результате образовавшейся команды ls examples? Конечно, содержимое каталога. Шаблон в последней команде из примера, "*[ao]*" был превращен в список файлов, чьи имена содержат "a" или "o" - Documents examples loop to.sort, а ключ "-d" потребовал от ls показывать информацию о каталогах, а не об их содержимом. В соответствии с ключом "-F", ls расставила "/" после каталогов и "*" после исполняемых файлов.

Еще одно отличие генерации имен от стандартной обработки шаблона - в том, что символ "/", разделяющий элементы пути, никогда не ставится в соответствие "*" или диапазону. Происходит это не потому, что искажен алгоритм, а потому, что при генерации имен шаблон применяется именно к элементу пути, внутри которого уже нет "/". Например, получить список файлов, которые находятся в каталогах /usr/bin и /usr/sbin и содержат подстроку "ppp" в имени, можно с помощью шаблона "/usr/*bin/*ppp*". Однако одного шаблона, который бы включал в этот список еще и каталоги /bin и /sbin - то есть подкаталоги другого уровня вложенности - по стандартным правилам сделать нельзя2).

Если перед любым специальным символом стоит "\", этот символ лишается специального значения, экранируется: пара "\символ" заменяется командным интерпретатором на "символ" и передается в командную строку без всякой дальнейшей обработки:


[methody@localhost methody]$ echo *o* Documents loop to.sort [methody@localhost methody]$ echo \*o\* *o* [methody@localhost methody]$ echo "*o*" *o* [methody@localhost methody]$ echo *y* *y* [methody@localhost methody]$ ls *y* ls: *y*: No such file or directory

Пример 8.8. Экранирование специальных символов и обработка "пустых" шаблонов (html, txt)

Мефодий заметил, что шаблон, которому не соответствует ни одно имя файла, bash раскрывать не стал, как если бы все "*" в нем были экранированы. В самом деле, какое из двух зол меньше: изменять интерпретацию спецсимволов в зависимости от содержимого каталога, или сохранять логику интерпретации с риском превратить команду с параметрами в команду без параметров? Если бы, допустим, шаблон, которому не нашлось соответствия, попросту удалялся, то команда ls *y* превратилась бы в ls и неожиданно выдала бы содержимое всего каталога. Авторы bash (как и Стивен Борн, автор самой первой командной оболочки - sh) выбрали более непоследовательный, но и более безопасный первый способ3).

Лишить специальные символы их специального значения можно и другим способом. В лекции 2 было рассказано, что разделители (пробелы, символы табуляции и символы перевода строки) перестают восприниматься как таковые, если часть командной строки, их содержащую, окружить двойными или одинарными кавычками. В кавычках перестает "работать" и генерация имен (как это видно из примера), и интерпретация других специальных символов. Двойные кавычки, однако, допускают выполнение подстановок переменной окружения и результата работы команды, описанных в двух следующих разделах.


Содержание раздела