Конструкции
if
Можно и так:
if python -c "exit(0)"; then echo OK; else echo FAIL; fi
если удобнее, if
можно записать в несколько строк:
if команда
then
тело
fi
if команда
then
тело
else
иначе_тело
fi
Выполнит или не выполнит тело в зависимости от того, завершилась команда с кодом возврата 0 (выполнит) или другим (не выполнит).
for
В shell есть циклы for
такого формата:
for var_name in набор значений
do
тело цикла
done
Тело цикла выполнится столько раз, сколько значений в наборе, и внутри тела переменная $var_name
будет установлена в соответствующее значение.
for i in 1 2 3; do echo $i; done
## вывод
1
2
3
Аргументы подаются так же, как и в любую другую команду, то есть можно, например, направить туда вывод чего-нибудь.
for
Аналог ls для бедных:
for i in *; do printf "%s\n" "$i"; done
Аналог for i in range(11):
из Python.
for i in $(seq 0 10);
do
echo $i;
echo $((10-i));
done
while
Также имеются циклы while
:
while команда
do
тело цикла
done
Тело цикла будет выполняться, пока команда не вернёт код ошибки, отличный от нуля.
while
Например, с помощью test будет ждать, когда появится файл x:
while ! test -f x; do sleep 1; done
здесь сначала исполняем команду test
, если код возврата отличен от 0 (т.е. файл не сущесвтует), то ! test
будет интерпретирован как 0
, поэтому будем ожидать через sleep 1
.
Или можно организовать чтение с помощью read:
printf "1 2\n3 4\n" | while read a b; do \
echo "$a;$b" \
done
case
case <переменная> in
образец1)
команды для образца1;;
образец2)
команды для образца2;;
*)
команды по умолчанию;;
esac
используется для сопоставления с образцом и ветвления потока выполнения в зависимости от соответствия образцу.
Пример
case $1 in
start)
echo "Запуск процесса";;
stop)
echo "Остановка процесса";;
*)
echo "Использование: $0 {start|stop}";;
esac
Этот скрипт принимает аргумент $1
и сопоставляет его с start
или stop
. В зависимости от аргумента выполняются соответствующие команды.
Если совпадение не найдено, используется образец *
, который является образцом по
умолчанию, т.к. ему соответствует любая строка.
test
test(1)
— полезная команда, с помощью которой можно проверять, например, существует ли какой-то файл, не директория ли это, равны ли две строки и так далее.
У этой команды есть синоним [
с дополнительным требованием, что вызов [
нужно завершать аргументом ]
.
$ [ 1 = 2
[: missing `]
$ test 1 = 2
$ echo $?
1
$ [ 1 = 1 ]
$ echo $?
0
Нужно понимать, что [
— имя команды, из-за чего нельзя писать [1=2]
без пробелов: такой команды попросту нет.
help
В некоторых шеллах есть встроенная команда help
, с помощью неё удобно смотреть документацию к другим встроенным выражениям, в т.ч. test:
help test
getopts
getopts
помогает разбирать аргументы на флаги, используется вместе с конструкцией case:
#!/bin/sh
usage() { echo "$0 [-s <45|90>] [-p <string>]" 1>&2; }
while getopts ":s:p:" o; do
case "${o}" in
s)
s=${OPTARG}
[ $s -eq 45 -o $s -eq 90 ] || usage
;;
p)
p=${OPTARG}
;;
*)
usage
;;
esac
done
shift $((OPTIND-1))
if [ -z "${s}" ] || [ -z "${p}" ]; then usage fi
Списки команд
Логическое И и логическое ИЛИ
Оператор | Описание |
---|---|
p1 && p2 | Если команда слева (p1 ) завершилась кодом возврата 0, то исполняем команду справа (p2 ) и возвращаем её код, иначе возвращаем код возврата команды слева (p1 ) |
p1 || p2 | Если команда слева (p1 ) закончилась кодом возврата отличным от 0, то исполняем команду справа (p2 ) и возвращаем её код, иначе возвращаем 0. |
Примеры уже упоминаемые ранее:
python -c 'exit(0)' && echo Success || echo Failure
## вывод
Success
python -c 'exit(1)' && echo Success || echo Failure
## вывод
Failure
Точка с запятой
Точка с запятой ;
используется для разделения нескольких команд, которые должны выполняться последовательно, независимо от успеха или неудачи предыдущей команды.
Например,
echo "Первая команда"; echo "Вторая команда"
должно выводить:
## вывод
Первая команда
Вторая команда
subshell
subshell - это отдельный дочерний процесс shell, который создается из родительского shell.
subshell наследует окружение (переменные окружения, текущий рабочий каталог и так далее) от родительской оболочки, но изменения, сделанные в subshell, не влияют на родительскую оболочку.
Это позволяет изолированно выполнять команды и скрипты.
Можно, вызвать с помощью круглых скобок ()
, см. ниже. Иногда создаётся и неявно, например, в
конвейерах.
Примеры:
1. Изменение текущей директории
В этом примере мы меняем директорию в subshell, и это не влияет на текущую директорию родительской оболочки.
(cd /tmp; ls)
echo "Текущая директория: $(pwd)"
Здесь команды внутри скобок (cd /tmp; ls)
выполняются в subshell, а pwd
показывает текущую директорию родительской оболочки.
Примеры:
2. Использование переменных
В этом примере переменная, определенная в subshell, не доступна в родительской оболочке.
(export MY_VAR="Hello"; echo $MY_VAR)
echo $MY_VAR
MY_VAR
будет выведена в subshell, но второй echo $MY_VAR
в родительской оболочке ничего не выведет, так как MY_VAR
не определена в родительской оболочке.
Примеры:
3. Использование в скриптах
Подоболочки полезны в скриптах для изоляции выполнения определенных частей скрипта.
#!/bin/bash
echo "Начало скрипта"
(
echo "В subshell"
# Выполнение команд в subshell
)
echo "Конец скрипта"
В этом скрипте команды внутри круглых скобок выполняются в subshell.
Использование subshell позволяет организовать более чистое и управляемое выполнение команд, ограничивая область видимости изменений и предотвращая побочные эффекты на родительскую оболочку.
Это особенно полезно в сложных скриптах и при выполнении операций, требующих временного изменения окружения или текущего рабочего каталога.
Круглые скобки
Круглые скобки ()
используются для группировки команд в subshell.
Подоболочка является отдельным дочерним процессом оболочки, и любые изменения в его среде не влияют на родительскую оболочку.
Например
(cd /some/directory; echo "Я в $(pwd)")
изменяет директорию только в subshell и выводит текущую директорию в нём же.
Фигурные скобки
Группировка команд с помощью фигурных скобок {}
похожа на круглые скобки,
но команды выполняются прямо в текущем shell, а не в subshell.
{ echo "Первая команда"; echo "Вторая команда"; }
выполняет обе команды echo
в текущем shell.