Иногда программы осуществляют вывод в стандартный поток диагностики, даже если они работают правильно. Типичным примером является программа time, которая выполняет команду и выдает в стандартный поток диагностики сообщение о том, сколько времени заняло выполнение:
$ time wc ch3.1
931 4288 22691 ch3.1
real 1.0
user 0.4
sys 0.4
$ time wc ch3.1 >wc.out
real 2.0
user 0.4
sys 0.3
$ time wc ch3.1 >wc.out 2>time.out
$ cat time.out
real 1.0
user 0.4
sys 0.3
$
Конструкция
2> имя_файла
(между
2
и
>
не должно быть пробелов) переключает стандартный поток диагностики на файл; синтаксически она непривлекательна, но служит своей цели. (Для такого короткого теста, как приведенный выше, время, выдаваемое командой
time
, не совсем правильное, но для последовательности больших тестов она выводит полезную информацию, которой можно доверять в разумных границах. Вы вполне можете сохранить ее для дальнейшего анализа; обратитесь, например, к таблице 8.1.)
Допустимо также слияние двух выходных потоков:
$ time wc ch3.1 >wc.out 2>&1
$ cat wc.out
931 4288 22691 ch3.1
real 1.0
user 0.4
sys 0.3
$
Обозначение
2>&1
является указанием интерпретатору, что стандартный поток диагностики нужно поместить в тот же поток, что и стандартный выходной. Амперсанд не содержит какого-либо мнемонического смысла; это просто идиома, которую следует запомнить. Для добавления стандартного выходного потока к стандартному потоку диагностики можно использовать
1>&2
:
echo ... 1>&2
В командных файлах это позволяет предотвратить исчезновение сообщений в файле или программном канале.
Интерпретатор предоставляет возможность размещать стандартный входной поток вместе с командой, а не в отдельном файле, так что командный файл может хранить всю информацию в себе самом. Наша справочная программа
411
, работающая с каталогом телефонов, могла быть задана так:
$ cat 411
grep "$*" <<End
dial-a-joke 212-976-3838
dial-a-prayer 212-246-4200
dial santa 212-976-3636
dow jones report 212-976-4141
End
$
Программирующие на языке
shell
называют такую конструкцию "документ здесь", т.е. входной поток находится здесь, а не в каком-нибудь файле. Началом конструкции служит
<<
; последующее слово (в нашем примере
End
) является ограничителем входного потока, включающего все строки до той, которая содержит только данное слово. Интерпретатор выполняет замену конструкций
$
,
`...`
и
\
в "документе здесь", если только часть слова не экранирована кавычками или обратной дробной чертой, — в этом случае весь документ берется без изменений. В конце главы мы рассмотрим еще более интересный пример с конструкцией "документ здесь".
В табл. 3.2 перечислены различные виды переключения ввода-вывода, допускаемые интерпретатором.
> файл
| Переключение стандартного выходного потока в файл |
>> файл
| Добавление стандартного выходного потока в файл |
< файл
| Получение стандартного выходного потока из файла |
p1 | p2
| Передача стандартного выходного потока программы p1 в качестве входного потока для программы p2
|
^
| Устарелый синоним |
|
n> файл
| Переключение выходного потока из файла с дескриптором n в файл |
n>> файл
| Добавление выходного потока из файла с дескриптором n в файл |
n>&m
| Слияние выходных потоков файлов с дескрипторами n и m
|
<<s
| "Документ здесь": берется стандартный входной поток до строки, начинающейся с s ; выполняется подстановка для $ , `...` и \
|
<<\s
| "Документ здесь" без подстановки |
<<'s'
| "Документ здесь" без подстановки |
Таблица 3.2: Переключение ввода-вывода интерпретатора
Упражнение 3.14
Сравните версии программы 411: использующую "документ здесь" и первоначальную. Какую легче сопровождать? Какая более подходит в качестве основы общего служебного средства?
3.8 Циклы в shell-программах
Язык
shell
— действительно язык программирования: в нем есть переменные, циклы, ветвления и т.п. Здесь мы обсудим основные циклы, а структуры управления рассмотрим более подробно в гл. 5.