Проблемы, вызванные литералами, могут быть неуловимыми. Допустим, вы ищете все записи в файле /etc/passwd, соответствующие регулярному выражению r.*t (то есть такие строки, которые содержат символ r и чуть далее символ t; это могло бы позволить вам отыскать такие имена пользователей, как root, ruth и robot). Можно запустить такую команду:
$ grep r.*t /etc/passwd
В большинстве случаев она будет срабатывать, но иногда по непонятной причине давать сбой. Почему? Ответ заключен, вероятно, в вашем корневом каталоге. Если этот каталог содержит файлы с такими именами, как r.input и r.output, то тогда оболочка развернет выражение r.*t в r.input r.output и создаст такую команду:
$ grep r.input r.output /etc/passwd
Ключом к обходу подобных проблем служит, во-первых, распознавание символов, которые могут вызвать неприятности, а затем — применение правильного типа кавычек, чтобы защитить символы.
11.2.2. Одинарные кавычки
Простейший способ создать литерал и сделать так, чтобы оболочка его не трогала, — поместить всю строку в одинарные кавычки, как в следующем примере с командой grep и символом *:
$ grep 'r.*t' /etc/passwd
Поскольку дело касается оболочки, все символы между двумя одинарными кавычками, включая пробелы, образуют единый параметр. Следовательно, приводимая ниже команда не будет работать, поскольку она просит команду grep выполнить поиск строки r.*t /etc/passwd в стандартном вводе (так как у команды grep здесь лишь один параметр):
$ grep 'r.*t /etc/passwd'
Когда вам необходимо использовать литерал, в первую очередь следует обратиться к одинарным кавычкам, так как при этом вы будете уверены в том, что оболочка не станет пытаться выполнить какие-либо подстановки. В результате синтаксис будет довольно ясным. Тем не менее иногда может потребоваться дополнительная гибкость, и тогда вам пригодятся двойные кавычки.
11.2.3. Двойные кавычки
Двойные кавычки (") действуют подобно одинарным, за исключением того, что оболочка развертывает все переменные, которые появляются внутри двойных кавычек. Можно увидеть это отличие, если запустить следующую команду, а затем заменить в ней двойные кавычки одинарными и выполнить команду повторно:
$ echo "There is no * in my path: $PATH"
При запуске этой команды обратите внимание на то, что оболочка выполняет подстановку для переменной $PATH, но не заменяет символ *.
примечание
Если вы используете двойные кавычки при выводе больших объемов текста, попробуйте использовать синтаксис heredoc, как описано в разделе 11.9.
11.2.4. Передача одинарной кавычки в литерале
Хитрый момент при использовании литералов в оболочке Bourne shell возникает тогда, когда необходимо передать команде одинарную кавычку как литерал. Один из способов это выполнить — поместить символ обратной косой черты перед знаком одинарной кавычки:
$ echo I don\'t like contractions inside shell scripts.
Обратная косая черта и кавычка
$ echo "I don't like contractions inside shell scripts."
Если вы в затруднении и вам необходимо общее правило для помещения всей строки в кавычки без подстановок, воспользуйтесь такой процедурой.
1. Замените все экземпляры ' (одинарная кавычка) на '\'' (одинарная кавычка, обратная косая черта, одинарная кавычка, одинарная кавычка).
2. Заключите всю строку в одинарные кавычки.
Следовательно, такую неуклюжую строку, как this isn't a forward slash: \, можно поместить в кавычки следующим образом:
$ echo 'this isn'\''t a forward slash: \'
примечание
Стоит еще раз упомянуть о том, что при помещении строки в кавычки оболочка расценивает все, что находится внутри них, как единый параметр. Следовательно, символы a b c представляют три параметра, а символы a "b c" — только два.
11.3. Специальные переменные
Большинство сценариев оболочки понимает параметры командной строки и взаимодействует с запускаемыми командами. Чтобы перевести ваши сценарии с уровня простого перечня команд на уровень более гибких приложений для оболочки, вам необходимо знать о том, как использовать специальные переменные оболочки Bourne shell. Эти специальные переменные подобны любым другим переменным оболочки, как рассказано в разделе 2.8, за исключением того, что значения некоторых из них нельзя изменить.
примечание