\n'
. Однако теперь, когда она говорила '\n'
, на самом деле она не произносила ничего, поэтому ей приходилось открывать рот дважды: один раз, чтобы сказать '\n'
, и второй раз, чтобы не сказать ничего. Это не понравилось обидчивому юноше, который тотчас сказал: "Для меня '\n'
звучит, как настоящее "ничего", но когда ты открываешь рот второй раз, то все портишь. Возьми второе "ничего" назад". Услужливая UNIX согласилась отказаться от некоторых эхо и обозначила это как '\c'
. С тех пор обидчивый юноша мог услышать совершенное эхо "ничего", если он задавал '\n'
и '\c'
вместе, но говорят, что он так и не услышал его, поскольку умер от излишеств в обозначениях.Упражнение 3.3Предскажите, что сделает команда
grep
в каждом случае, а затем проверьте себя;grep \$ grep \\
grep \\$ grep \\\\
grep \\\\$ grep "\$"
grep '\$' grep '"$'
grep '\'$ grep "$"
Файл, состоящий из таких команд, послужит хорошим материалом для теста, если вы хотите поэкспериментировать.
Упражнение 3.4Как указать
grep
, что нужно найти шаблон, начинающийся с '-'
? Почему взятие аргумента в кавычки не помогает? Подсказка: исследуйте флаг -е
.Упражнение 3.5Рассмотрите команду
$ echo */*
Может ли она вывести все имена всех каталогов? В каком порядке появятся эти имена?
Упражнение 3.6(Хитрый вопрос.) Как ввести
/
в локальное имя файла (т.е. символ /
, который не является разделителем компонентов в абсолютном имени)?Упражнение 3.7Что произойдет в случае ввода команд
$ cat x y >y
и $ cat x >>x
Подумайте, прежде чем броситься их выполнять.
Упражнение 3.8Если вы введете
$ rm *
почему команда
rm
не сможет предупредить вас, что вы собираетесь удалить все ваши файлы?3.3 Создание новых команд
Теперь, как мы обещали вам в гл. 1, рассмотрим создание новых команд из старых. Имея последовательность команд, которую придется многократно повторять, преобразуем ее для удобства в "новую" команду со своим именем и будем использовать ее как обычную команду. Чтобы быть точными, предположим, что нам предстоит часто подсчитывать число пользователей с помощью конвейера
$ who | wc -l
(см. гл. 1), и для этой цели нужна новая программа
nu
.Первым шагом должно быть создание обычного файла, содержащего
'who | wc -l'
. Можно воспользоваться вашим любимым редактором или проявить изобретательность:$ echo 'who | wc -l' >nu
(Что появится в файле
nu
, если не употреблять кавычки?)Как отмечалось в гл. 1, интерпретатор является точно такой же программой, как редактор,
who
или wc
; он называется sh
. А коль скоро это программа, ее можно вызвать и переключить ее входной поток. Так что запускаем интерпретатор с входным потоком, поступающим из файла nu
, а не с терминала:$ who
you tty2 Sep 28 07:51 rhh tty4 Sep 28 10:02
moh tty5 Sep 28 09:38 ava tty6 Sep 28 10:17
$ cat nu who | wc -l
$ sh < nu
4
$
Результат получился таким же, каким бы он был при задании команды
who | wc -l
с терминала. Опять-таки, как и большинство программ, интерпретатор берет входной поток из файла, если он указан в качестве аргумента; вы с тем же успехом могли задать:$ sh nu
Однако досадно вводить "
sh
" каждый раз; во всяком случае эта запись длиннее и создает различия между программами, написанными, например, на Си, и программами, написанными с помощью shell
.[9] Поэтому если файл предназначен для выполнения и если он содержит текст, то интерпретатор считает, что он состоит из команд. Такие файлы называются командными. Все, что вам нужно сделать, это объявить файл nu
выполняемым, задав$ chmod + x nu
а затем вы можете вызывать его посредством
$ nu
С этого момента те, кто используют файл nu, не смогут определить способ его создания.
Способ, с помощью которого интерпретатор на самом деле выполняет
nu
, сводится к созданию нового процесса интерпретатора, как если бы вы задали$ sh nu
Этот процесс-потомок называется порожденным интерпретатором, т.е. процессом интерпретатора, возбужденным вашим текущим интерпретатором. Но команда
sh nu
— это не то же самое, что sh < nu
, поскольку в первом случае стандартный входной поток все еще связан с терминалом. Пока команда nu
выполняется только в том случае, если она находится в вашем текущем каталоге (при условии, конечно, что текущий каталог включен в PATH
, а именно это мы и предполагаем с настоящего момента). Чтобы сделать команду nu частью вашего репертуара независимо от того каталога, с которым вы работаете, занесите ее в свой собственный каталог bin
и добавьте /usr/you/bin
к списку каталогов поиска:$ pwd /usr/you
$ mkdir bin
Создать bin, если его еще не было$ echo $PATH
Проверить Path, чтобы убедиться:/usr/you/bin:/bin:/usr/bin
Должно быть нечто похожее$ mv nu bin
Установить команду nu в bin$ ls nu
nu not found
Она действительно исчезлаиз текущего каталога
$ nu
4
Но интерпретатор ее находит$
Конечно, ваша переменная
PATH
должна быть правильно определена в файле .profile
, чтобы вам не приходилось переопределять ее при каждом входе в систему.Существуют и другие простые команды, которые вы можете адаптировать к среде по своему вкусу и создавать таким же способом. Нам показалось удобным иметь следующие команды:
•
cs
для посылки подходящей последовательности специфических символов с целью очистки экрана вашего терминала (24 символа перевода строки — практически универсальное решение);•
what
для запуска who
и ps -а
, чтобы сообщить, кто работает в системе и что он делает;•
where
для вывода идентифицированного названия используемой системы UNIX. Это удобно, если вы постоянно работаете с несколькими версиями. (Установка PS1
служит для подобной цели.)Упражнение 3.9Просмотрите каталоги
/bin
и /usr/bin
, чтобы выяснить, как много команд являются в действительности командными файлами. Можно ли это сделать с помощью одной команды? Подсказка: посмотрите file(1)
. Насколько точно предположение, основанное на длине файла?3.4 Аргументы и параметры команд
Хотя команда
nu
, как она задумывалась, удовлетворяет своему назначению, многие программы на языке shell
могут обрабатывать аргументы, так что при их запуске можно задавать имена файлов и флаги.Допустим, вы хотите создать программу с именем
cx
для установки права доступа к файлу на выполнение, так что$ cx nu
есть сокращенная запись для
$ chmod +x nu
Вы уже знаете почти все, чтобы это сделать. Вам нужен файл
cx
, содержимое которого суть