Элементы, выделенные жирным шрифтом, управляют синтаксисом heredoc. Маркер < Обратите внимание на переменную $DATE в приведенном примере. Оболочка раскрывает переменные оболочки внутри документов с синтаксисом heredoc, это особенно полезно, когда вы выводите отчеты, которые содержат много переменных. 11.10. Основные утилиты в сценариях оболочки Некоторые команды чрезвычайно полезно применять в сценариях оболочки. Такие утилиты, как basename, пригодны лишь при использовании с другими командами и, следовательно, нечасто встречаются за пределами сценариев. Тем не менее другие команды, например awk, могут быть полезными и в командной строке. 11.10.1. Команда basename Если вам необходимо удалить расширение из имени файла или изъять названия каталогов из полного пути, воспользуйтесь командой basename. Попробуйте ввести в командную строку следующие примеры, чтобы понять, как работает эта команда: $ basename example.html.html $ basename /usr/local/bin/example В обоих случаях команда basename возвращает результат example. Первая команда удаляет суффикс. html из имени файла example.html, а вторая — названия каталогов из полного пути. Следующий пример демонстрирует, как применить команду basename в сценарии, который конвертирует файлы изображений из формата GIF в формат PNG: #!/bin/sh for file in *.gif; do # exit if there are no files if [! -f $file]; then exit fi b=$(basename $file.gif) echo Converting $b.gif to $b.png… giftopnm $b.gif | pnmtopng > $b.png done 11.10.2. Команда awk Команда awk не является простой командой с единственным способом применения; на самом деле это мощный язык программирования. К сожалению, искусство применения языка awk сейчас практически утрачено, поскольку его заменили более развитые языки, такие как Python. Языку awk посвящены целые книги, например $ ls — l | awk '{print $5}' Эта команда выводит пятое поле из отчета команды ls (размер файла). В результате получится список, содержащий размеры файлов. 11.10.3. Команда sed Команда sed (сокращение от Хотя команда sed является довольно большой и ее детальное рассмотрение выходит за рамки этой книги, легко понять, как она устроена. В общих чертах, команда sed воспринимает адрес и операцию как один аргумент. Адрес является набором строк, и команда решает, что делать с этими строками. Очень распространенная задача для команды sed: заменить какое-либо регулярное выражение текстом (см. подраздел 2.5.1), например, так: $ sed 's/ Так, если вы желаете заменить первое двоеточие в файле /etc/passwd на символ %, а затем отправить результат в стандартный вывод, следует выполнить следующую команду: $ sed 's/:/%/' /etc/passwd Чтобы заменить $ sed 's/:/%/g' /etc/passwd Приведу команду, которая работает построчно; она считывает файл /etc/passwd и удаляет строки с третьей по шестую, а затем отправляет результат в стандартный вывод: $ sed 3,6d /etc/passwd В этом примере число 3,6 является адресом (диапазоном строк), а флаг d — операцией (удаление). Если адрес опустить, команда sed будет работать со всеми строками входного потока. Двумя самыми распространенными операциями команды sed являются s (найти и заменить) и d. В качестве адреса можно также использовать регулярное выражение. Эта команда удаляет любую строку, которая соответствует регулярному выражению $ sed '/ 11.10.4. Команда xargs Когда вам приходится запускать одну команду для большого количества файлов, то эта команда или оболочка может ответить, что она не способна вместить все аргументы в свой буфер. Чтобы справиться с этой проблемой, используйте команду xargs, запуская ее в стандартном потоке ввода для каждого имени файла. Многие применяют команду xargs вместе с командой find. Например, следующий сценарий может помочь проверить, что в текущем каталоге каждый файл с расширением. gif действительно является изображением в формате GIF (Graphic Interchange Format, формат обмена графическими данными): $ find. -name '*.gif' — print | xargs file В приведенном примере команда xargs запускает команду file. Однако такой вызов может привести к ошибкам или подвергнуть вашу систему рискам, связанным с безопасностью, поскольку имена файлов могут содержать пробелы и символы перевода строки. При написании сценариев используйте приводимую ниже форму, которая изменяет выходной разделитель команды find и разделитель аргументов команды xargs — вместо символа перевода строки применяется символ NULL: $ find. -name '*.gif' — print0 | xargs -0 file Команда xargs запускает множество процессов, поэтому не ожидайте высокой производительности, если вы работаете с большим количеством файлов. Может потребоваться добавить два дефиса (—) в конце команды xargs, если есть вероятность того, что название какого-либо целевого файла начинается с дефиса (-). Двойной дефис (—) можно применять, чтобы сообщить какой-либо команде, что аргументы, которые за ним следуют, являются именами файлов, а не параметрами. При этом помните, что не все команды поддерживают использование двойного дефиса. Есть альтернатива команде xargs при применении команды find: параметр — exec. Однако ее синтаксис довольно мудреный, так как вам необходимо использовать символы {} для подстановки имени файла и литерал;, чтобы указать окончание команды. Вот как выполняется предыдущая задача с помощью одной лишь команды find: $ find. -name '*.gif' — exec file {} \; 11.10.5. Команда expr Если вам необходимо использовать арифметические операторы в сценариях оболочки, может прийти на помощь команда expr (которая выполняет даже некоторые операции со строками). Например, команда expr 1 + 2 выводит результат 3. Запустите команду expr — help, чтобы получить полный перечень операций. Применение команды expr — это неуклюжий и медленный способ выполнения математических вычислений. Если вам часто приходится заниматься ими, то, вероятно, лучше использовать что-либо вроде языка Python вместо сценария оболочки. 11.10.6. Команда exec Команда exec является встроенной в оболочку функцией, которая заменяет текущий процесс оболочки той командой, которую вы укажете после команды exec. Она осуществляет системный вызов exec(), о котором вы узнали из главы 1. Эта функция предназначена для сохранения системных ресурсов, однако помните о ее необратимости: если запустить команду exec в сценарии оболочки, то этот сценарий и сама оболочка прекратят работу, уступив место новой команде. Чтобы проверить это в окне оболочки, попробуйте запустить команду exec cat. После нажатия сочетания клавиш Ctrl+D или Ctrl+C для завершения команды cat окно оболочки должно исчезнуть, поскольку его дочерний процесс больше не существует. 11.11. Подоболочки Предположим, вам необходимо немного изменить среду в оболочке, но это изменение не должно стать постоянным. Можно изменить, а потом вернуть в исходное состояние часть среды (например, путь или рабочий каталог), используя переменные оболочки, однако такой способ довольно груб. Простой вариант выполнения подобных задач заключается в применении Чтобы использовать подоболочку, поместите в скобки те команды, которые она должна выполнить. Например, следующая строка выполняет команду uglyprogram в каталоге uglydir, оставляя исходную оболочку без изменений: $ (cd uglydir; uglyprogram) Следующий пример показывает, как добавить компонент пути, который может вызвать проблемы, если сделать это изменение постоянным: $ (PATH=/usr/confusing:$PATH; uglyprogram) Использование подоболочки для выполнения одноразового изменения среды является настолько распространенным, что существует даже встроенный синтаксис, который не прибегает к подоболочке: $ PATH=/usr/confusing:$PATH uglyprogram Каналы и фоновые процессы также работают в подоболочках. Следующий пример использует команду tar для архивирования всего дерева каталогов внутри каталога orig, а затем распаковывает этот архив в новый каталог target, дублируя тем самым файлы и папки каталога orig (это оправданно, поскольку при этом сохраняются сведения о владельцах и правах доступа, и это обычно выполняется быстрее, чем команда типа cp — r): $ tar cf — orig | (cd target; tar xvf — ) внимание Тщательно проверяйте подобные команды перед их запуском, чтобы убедиться в том, что каталог target существует и он абсолютно отличается от каталога orig. 11.12. Включение других файлов в сценарии Если вам необходимо включить другой файл в сценарий оболочки, используйте оператор «точка» (.). Например, такая строка выполняет команды из файла config.sh: config.sh Подобный синтаксис «включения» не запускает подоболочку и может быть полезен для группы сценариев, которым необходимо использовать единственный файл конфигурации. 11.13. Чтение пользовательского ввода Команда read считывает строку текста из стандартного ввода и сохраняет ее текст в переменной. Например, следующая команда сохраняет ввод в переменной $var: $ read Эта встроенная в оболочку команда может оказаться полезной в сочетании с другими функциями оболочки, не упомянутыми в данной книге. 11.14. Когда (не) использовать сценарии оболочки Оболочка настолько богата функциями, что трудно рассказать обо всех ее важнейших элементах в одной главе. Если вы заинтересовались, на что еще способна оболочка, загляните в одну из книг, посвященных программированию в оболочке (например, Но, несмотря на это, в некоторый момент (особенно если вы начинаете пользоваться встроенной командой read), вы должны задать себе вопрос: применяете ли вы по-прежнему верный инструмент для работы? Вспомните, с чем лучше всего справляются сценарии оболочки: это работа с простыми файлами и командами. Как уже было сказано выше, если вам приходится писать что-либо замысловатое, а в особенности задействовать сложные строковые или арифметические операции, вероятно, лучше обратиться к таким языкам сценариев, как Python, Perl или awk.