Bash Scripting Guide/Commands
Материал из Wiki.UnixForum.org
Содержание |
Команды и комментарии
Любая строка скрипта является командой(несколькими командами), которая выполняется bash'ем. Также, в bash'е существуют комментарии -- куски кода, которые не выполняются ни при каких условиях. Комментарием считается всё, что стоит после символа #.
Например, строка:
# abc
Состоит только из комментария.
Примером команды может служить:
ls
Либо команда с аргументами:
echo hello
Двойные/одинарные кавычки и экранирование
Аргументы команд разделяются пробелами. Соответственно, для того, чтобы передать как один аргумент строку, содержащую в себе пробел, необходимо заключить эту строку в двойные или одинарные кавычки. Этот же приём позволит передать специальные символы в качестве аргумента.
Например,
echo hello > file
Запишет в файл file строку hello, а на экран ничего не выведет (см. Потоки ввода-вывода).
Тогда как:
echo 'hello > file'
Выведет
hello > file
В кавычки можно заключить даже перевод строки, он тоже потеряет при этом своё специальное назначение - завершение команды:
echo "first line second line"
Выведет
first line second line
Для вывода кавычек (хотя и для вывода других специальных символов его тоже можно использовать) есть приём, называемый экранированием, когда перед нужным нам символом ставится обратная косая черта:
echo \"
Для вывода обратной косой черты нужно её "удвоить":
echo \\
Оба этих способа вывода специальных символов почти равнозначны, так что выбор остаётся за вами (где-то быстрее поставить \, где-то кавычки).
Специальные символы
; # " ' ` \ $ ( ) [ ] { } > < & |
И некоторые другие в зависимости от контекста.
Подробнее можно прочитать по адресу: ABS Special Chars
Возвращаемые значения
Любая выполненная команда возвращает какое-то численное значение, по которому можно определить правильно выполнилась команда или нет. На основании этого возвращаемого значения можно и построить дальнейшую логику скрипта (например, выслать письмо администратору :-)).
Хозяйке на заметку: Принято, что:
|
Значение, возвращённое последней выполненной командой, находится в переменной $?.
Например,
ls /bad_folder/ echo $?
Выведет 1, так как /bad_folder/ не существует.
Выполнение нескольких команд
Первоначально, одна строчка -- одна команда. Для того, чтобы выполнить несколько команд в одной строке можно воспользоваться одним из трёх способов:
- разделить команды точкой с запятой:
echo a; ls
Выполнит сначала команду echo, а потом ls
- разделить команды двумя подряд идущими амперсандами:
echo a && ls
В таком случае вторая команда (ls) выполнится лишь в случае, когда первая команда (echo) вернёт 0, то есть выполнится без ошибок
- разделить команды двумя подряд идущими вертикальными чертами:
echo a || ls
В этом же случае вторая команда выполнится только тогда, когда первая команда вернёт не 0, то есть выполнится с ошибкой
Команды можно группировать, объединяя их круглыми скобками.
Например,
ls /bad_file/ || ( echo a; echo b )
В таком случае содержимое круглых скобок, то есть:
echo a; echo b
Будет выполняться в отдельном подпроцессе bash'а. Что важно, например, при использовании exit -- будет завершён только подпроцесс, а основной процесс продолжит своё выполнение.
Чтобы подпроцесс не порождался, команды нужно объединять фигурными скобками.
Например, в случае
ls /bad_file/ || { echo a; echo b; }
echo a и echo b выполнятся только в том случае, если ls завершится с ошибкой. И они будут выполняться без порождения подпроцесса. Хочу обратить внимание, что точка с запятой после последней команды обязательна (в отличие от варианта с круглыми скобками, где точка с запятой возможна, но не обязательна).
Стоит отметить, что можно объединить несколько строк в одну (то есть bash будет считать их одной строкой) для этого в конце строке надо поставить один \:
echo a\ b
выведет ab (без пробелов!).
Потоки ввода/вывода
В любой программе существует три потока ввода/вывода:
- stdin
Используется для ввода данных в программу. - stdout
Используется для вывода данных. - stderr
Используется для вывода ошибок.
В bash'е каждый из этих потоков можно перенаправлять в файлы или друг в друга.
То есть
echo a > file
Перенаправит stdout в file, то есть a выведется не на экран, а перезапишет файл file.
Символ > является короткой записью для 1>, где 1 обозначает stdout. Для обозначения stderr нужно использовать 2.
Так, после
ls /bad_file/ 2>file
В файле file окажется строки ошибки:
ls: /bad_file/: No such file or directory
Так как > переписывает содержимое файла, то для дописывания в конец файла существует последовательность >> (перед ней так же возможны 1 и 2).
Например, после нескольких запусков:
ls /bad_file/ 2>file
В файле file так и останется одна строчка (содержимое файла будет при каждом вызове перезаписываться). Тогда как после нескольких выполнений
ls /bad_file/ 2>>file
В файле file будет содержаться несколько строчек (при каждом новом вызове будет дописываться ещё одна строка с ошибкой).
Ещё возможно перенаправить stdout в текущий stderr и наоборот. Для этого сразу после > или >> нужно дописать не имя файла, а амперсанд и номер потока:
ls /bad_file/ 2>&1
Перенаправит весь вывод stderr в stdout.
Также, можно сразу перенаправить оба потока в один и тот же файл:
ls /bad_file/ &>file
Правда, в такой форме записи невозможно дописывать в файл -- только перезаписывать.
Поток stdin перенаправляется символом <.
Например,
mysql < file
Будет считывать запросы из файла file, а не с экрана.
Хозяйке на заметку:
ls /bad_file/ 2>&1 >file И ls /bad_file/ >file 2>&1 Это разные перенаправления. В первом случае stderr перенаправляется в stdout, а потом только stdout перенаправляется в файл file (stderr выводится на экран -- в момент перенаправления stdout указывал именно туда). Во втором случае сначала stdout перенаправляется в файл file, а затем туда же перенаправляется вывод stderr, то есть оба потока пишутся в файл file. |
Конвейеры
Конвейеры позволяют создавать цепочки программ, выполняющихся друг за другом, в которой каждая следующая программа будет оперировать с результатом предыдущей программы.
Конвейер перенаправляет stdout одной программы в stdin другой (вместо вывода на экран).
Например,
echo "b a" | sort
Здесь echo выводит в stdout
b a
А затем этот вывод перенаправляет в stdin программы sort (потом вывод sort можно перенаправить куда-нибудь ещё, а потом ещё...).
Результатом будет:
a b
Вообщем-то, благодаря конвейерам, у меня уже вошло в привычки писать:
cat file | grep "something"
Вместо
grep "something" file
В результате получится одно и то же, но если, например, я только что просматривал файл полностью (cat file), то первый вариант пишется быстрее. :-)
