Синтаксис bash

Краткий свод управляющих конструкций языка программирования bash.

Во всех управляющих конструкциях в качестве логического значения используется код возврата из программы, указанной в качестве условия. Код возврата 0 – истина, любое другое значение – ложь. Программа true – всегда завершается с кодом 0, false – всегда завершается с кодом 1. Команда test (она же [...] ) вычисляет код ответа на основе выражения, переданного через параметры командной строки.

Конструкции могут быть записаны в несколько строк, или в одну с использованием разделителя ";".

Последовательности команд. Возвращают код ответа последней выполненной команды.
; - оператор безусловного последовательного выполнения команд
&& оператор И. Правая часть не выполняется если левая выполнилась неуспешно.
|| оператор ИЛИ. Правая часть не выполняется если левая выполнилась успешно.

Оператор if – условное выполнение.
if cmd
then
command...
else
command...
fi

Запись в одну строку
if cmd ; then command1;command2…;else command3;command4…;fi

Цикл while выполняется, пока команда условие возвращает 0
while condition-is-true
do
command...
done
Запись в одну строку
while cmd; do command1; command2;done

Пример с использованием встроенной функцией test
VAR0=0; LIMIT=10
while [ "${VAR0}" -lt "${LIMIT}" ];do
echo -n "${VAR0} " # -n подавляет перевод строки
VAR0=`expr ${VAR0} + 1`
done

Пример в сочетании c арифметической подстановкой
a=1
while (( a <= LIMIT )) ; do # В (()) $ не нужен
echo -n "$a "
((a += 1)) # В арифметической подстановке есть оператор +=
done

Пример с командой read, которая read читает строки из стандартного ввода. read разбивает строку на слова и сохраняет их в указанных переменных. Если переменные не заданы, то read сохраняет всю строку в переменной REPLY. Если необходимо читать посимвольно, то команде read можно указать опцию -n 1
while read; do
echo $REPLY
done < file.txt

Цикл until аналогичен while, но выполняется пока команда завершается с ненулевым кодом возврата
until condition-is-true; do
command...
done

Цикл for выполняется путем последовательной подстановки в переменную цикла значений из списка
for ARG in LIST; do
command...
done

Простая форма
for ARG in "$VAR1" "$VAR2" "$VAR3" ; do
echo $ARG
done

В сочетании с подстановкой имен файлов по шаблону
for FILE in [ab]*; do
echo "$FILE" # В отличие от echo [ab]*, имена печатаются в отдельных строках
done

В сочетании с арифметической подстановкой
LIMIT=5
for ((a=1; a <= LIMIT ; a++)); do # $ не нужен ни перед скобками ни перед именами переменных
echo -n "$a "
done

В сочетании с программой seq
LIMIT=5
for ARG in `seq 1 $LIMIT`;do
echo -n "$ARG "
done

Оператор case выбор одного из вариантов в соответствии со значением аргумента
case "$VARiable" in
"$condition1" )
command...
;;
"$condition2" )
command...
;;
esac

Переменные в bash

Переменная в языке shell - это макрос, который может быть подставлен в строку команды перед её разбором. Оператор ${VAR} заменяется текстовой строкой, хранящейся в переменной с именем VAR. После подстановки значение переменной будет разбито на отдельные слова по пробельным символам. Если содержимое переменной должно интерпретироваться как одно слово, то оператор подстановки надо взять в кавычки "${VAR}"

Интерпретатор `bash` использует как минимум три типа переменных, отличающихся областью видимости:

A=BCD # Локальная переменная, доступная из данного скрипта
A=BCD cmd # Именованный параметр, передаваемый в окружение программы cmd не влияющий на текущий скрипт
export A=BCD # Глобальная переменная, видимая в текущем скрипте и в запускаемых программах

Переменные в bash не имеют типа. Можно считать, что переменная всегда содержит текстовую строку. Если требуется интерпретация переменной как числа, то проводится разбор строки слева. Значение определяют цифры до первого нечислового символа. Строка не содержащая цифр интерпретируется как 0.

set – выдает список всех переменных с их значениями

VAR="string" - определяет локальную переменную интерпретатора и присваивает ей значение. Разделителями в команде являются символ = после имени переменной и первый пробел после значения. Пробелы вокруг знака равенства недопустимы. Пробел слева от знака равенства интерпретируется как часть имени, пробел справа – как пустая присваеваемая строка. Если строка содержит пробелы, то она должна быть заключена в кавычки.
$VAR – подстановка значения переменной VAR. При разборе строки именем переменной считается максимальная последовательность из букв, цифр и знаков подчеркивания.
${VAR} - то же что и $VAR позволяет избавиться от неоднозначности при разборе строки

export VAR делает переменную доступной для дочерних процессов (делает переменную глобальной)
export VAR=string допустимое объявление глобальной переменной
unset VAR уничтожает определение переменной

Пример экспорта переменной:
WORKDIR=/usr/src/linux
echo $WORKDIR #используем значение переменной
bash #запустили новую копию интерпретатора
echo $WORKDIR #переменная недоступна
exit # завершили копию интерпретатора
echo $WORKDIR #переменная снова доступна
export WORKDIR
bash
echo $WORKDIR #после экспорта переменная доступна запускаемым программам

Дополнительные возможности при работе с переменными

${VAR-default} - если VAR определена, то ее значение иначе значение default
${VAR=default} - если VAR определена, то ее значение иначе значение default и присваивание его VAR
${VAR?err_msg} - если VAR определена, то ее значение иначе печать err_msg
Пример подстановки вывода команды whoami в качестве значения по умолчанию:
echo ${username-`whoami`}

${#VAR} - длина значения переменной в символах
${#array[*]} или ${#array[@]} - размер массива (Массивы доступны в версии bash > 2)
${#*} или ${#@} число параметров скрипта

${VAR:pos} - подстрока с позиции pos
${VAR:pos:len} - подстрока с позиции pos длинной length

В следующих операциях Pattern это выражение в формате glob - * - любая последовательность символов, ? - один символ.

${VAR/Pattern/Replacement} - замена первого вхождения Pattern на Replacement, если Replacement отсутствует, то Pattern удаляется
${VAR//Pattern/Replacement} - глобальная замена
$(VAR#Pattern} - удаление минимальной строки, соответствующей Pattern в начале строки (удаление префикса)
$(VAR##Pattern} - удаление максимальной строки, соответствующей Pattern в начале строки
$(VAR%Pattern} - удаление минимальной строки, соответствующей Pattern в конце строки (удаление суффикса)
$(VAR%%Pattern} - удаление максимальной строки, соответствующей Pattern в конце строки

Пример:

VAR="file.test.txt"
echo ${VAR#file*.} => test.txt
echo ${VAR##file*.} => txt
echo ${VAR%.*} => file.test
echo ${VAR%%.*} => file

Спецсимволы в bash

Далее перечислены символы и синтаксические конструкции, имеющее особое значение в bash. Для ввода спецсимволов как они есть используют кавычки или спецсимвол \ отменяющий специальное значение следующего символа

\ Экранирование. Отменяет специальное значение следующего символа
\\ Символ "\"

# Комментарий, не работает в кавычках и в некоторых подстановках переменных и преобразовании основания чисел
echo "Это #не комментарий"
echo 'Это # не комментарий’
echo Это \# не комментарий
echo Это # Вот комментарий.
echo ${PATH#*:} #Специальная переменная
echo $(( 2#101011 )) #Преобразование системы счисления в арифметической подстановке.

>, >> - перенаправление стандартного вывода программы в файл
< - перенаправление стандартного ввода программы из файла
<<TERM перенаправление стандартного ввода программы из текста текущего скрипта со следующей строки до строки, состоящей из слова TERM.
|- перенаправление стандартного вывода программы на стандартный ввод другой программы

; Разделитель команд в строке
echo hello; echo world

;; Разделитель альтернатив в операторе case
case "$VARiable" in
abc) echo "$VARiable = abc" ;;
xyz) echo "$VARiable = xyz" ;;
esac

. Аналог команды source (#include в С++). Выполняет скрипт в текущем интерпретаторе.
. myconf

".." Двойные кавычки, отменяют действие спецсимволов кроме $ `..` и \

'...' Апострофы, отменяют действие всех спецсимволов в том числе и \, по этому нельзя включить апостроф в строку ограниченную апострофами

: Нулевая команда, всегда возвращает нулевой код ответа. В сочетании с перенаправлением ">" создает файл, или обнуляет существующий. В сочетании с перенаправлением ">>" создает файл, или изменяет время модификации существующего
:> data.xxx # File “data.xxx” now empty.
(можно и без двоеточия)

Шаблоны в именах файлов. Если подходящие имена находятся, то они подставляются в командную строку как отдельные аргументы (возможно с пробелами внутри). Если имена не находятся, то шаблон остается как есть.

* Шаблон заменяющий любую последовательность символов
? Шаблон заменяющий ровно один символ
[xyz] Шаблон заменяющий один из перечисленных символов
{xxx,yyy,zzz,...} Подстановка одного из вариантов в шаблон. В скобках не должно быть неэкранированных пробелов
grep Linux file*.{txt,htm*} # Ищет слово “Linux” в файлах вида “fileA.txt”, “file2.txt”, “fileR.html”, “file-87.htm”, etc.

$ Подстановка значения переменной, арифметического выражения или стандартного вывода программы. Если значение содержит пробелы, то при подстановке оно разбивается на отдельные аргументы.
$A содержимое переменной A
$$ PID процесса
$? Код возврата из последней выполненной программы или функции, а также код возврата самого скрипта
$((2*2)) подстановка результата вычисления арифметического выражения
$(cmd) подстановка стандартного вывода программы
`...` тоже, что и $(...) – подстановка стандартного вывода программы

Пример: A=EE; echo $A $(echo QQ) $((7+5))
Результат: EE QQ 12
Ошибка: $A=ZZ
Результат: bash: EE=ZZ: command not found

(...) Группировка команд
(A=hello; echo $A)
Для выполнения группы в скобках запускается новый интерпретатор
A=123
(A=321)
echo A = $A # A = 123
# "A" внутри скобок – локальная переменная.

(...) Создание массива ( только в bash версии > 2)
Array=(element1 element2 element3)

[] Элемент массива ( только в bash версии > 2)
Array[1]=slot_1
echo ${Array[1]}

{1..10} - подстановка чисел от 1 до 10
{c..n} - подстановка символов от "c" до "n"

{...} Создание безымянной функции, удобно для перенаправления ввода/вывода нескольких команд в один файл. В отличие от настоящей функции видимости переменных не изменяется.
PACK=mysql
{
echo
echo "Archive Listing:"
rpm -qpl ${PACK} # Список фалов в пакете rpm
echo
rpm -i --test ${PACK} # Проверка, установлен ли пакет.
} > "${PACK}.txt" #И весь вывод в один файл.

[...] Встроенная функция test для вычисления логических выражений

((...)) Арифметическая подстановка, вычисляет арифметическое выражение в стиле языка Си внутри скобок

& - запуск программы в фоновом режиме
bash$ sleep 10 &
[1] 850
[1]+ Done sleep 10