Самый минимум для нормально программирования на bash:
- Нужно использовать полные названия опций
logger --priority
вместоlogger -p
set -o errexit
,set -e
- выходит из скрипта при ошибке|| true
- разрешает команде выполняться с ошибкойset -o nounset
,set -u
- выходить при обращении к неопределённой переменнойecho ${NAME:-bubujka}
- значение по умолчанию, если переменная не определенаset -o xtrace
,set -x
- печатать каждую команду что исполняетсяset -o pipefail
- обрывать выполнение если хоть одна команда в пайпе вернула ненулевой статус.mysqldump | gzip
- Переменные нужно брать в фигурные скобки
ls /srv/${ENV}_app
Несколько самых частых хоткеев, которые сильно облегчают работу в bash:
alt-b
на слово назадalt-f
на слово вперёдctrl-p
предыдущая командаctrl-n
следующая командаctrl-w
удалить слово левееctrl-k
удалить до конца строки вправоctrl-e
в конец строкиctrl-a
в начало строки
Подавляем stdout и stderr
$ ls /ololo /etc/ &> /dev/null
Проверяем нахождение подстроки в строке
string='My string';
if [[ "$string" == *My* ]]
then
echo "It's there!";
fi
needle='y s'
if [[ "$string" == *"$needle"* ]]; then
echo "haystack '$string' contains needle '$needle'"
fi
It's there!
haystack 'My string' contains needle 'y s'
$ I=foobar
$ echo ${I/oo/aa} #replacement
faabar
$ echo ${I:1:2} #substring
oo
$ echo ${I%bar} #trailing substitution
foo
$ echo ${I#foo} #leading substitution
bar
Добавить параметры предыдущей команды
$ ls /var/cache/
fontconfig hald ldconfig man pacman
$ cd <Alt+.>
$ cd /var/cache
Выполнить вторую команду с конца истории
$ ls -l foo bar
$ touch foo bar
$ !-2
Использовать аргументы предыдущей команды
$ ls -l foo
$ touch !:2
$ cp !:1 bar
Использование аргументов одной из предыдущих команд
$ ls -l foo bar
$ touch !:2 !:3
$ rm !-2:2 !-2:3
$ !-3
Подставить все аргументы предыдущей команды
$ ls -l foo bar
$ ls !*
Использовать первый аргумент предыдущей команды
$ ls /tmp /var
$ ls !^
Использовать последний аргумент предыдущей команды
$ ls /tmp /var
$ ls !$
Посмотреть какая команда будет выполнена:
$ ls /var /tmp
$ ls !$ <alt+shift+6>
$ ls /tmp
Использование случайных чисел
$ echo $((RANDOM % 15))
Проверка строки по регулярному выражению
if [[ "mystring" =~ REGEX ]] ; then
echo match
fi
Использование массивов
#!/bin/bash
array[0]="a string"
array[1]="a string with spaces and \"quotation\" marks in it"
array[2]="a string with spaces, \"quotation marks\" and (parenthesis) in it"
echo "There are ${#array[*]} elements in the array."
for n in "${array[@]}"; do
echo "element = >>${n}<<"
done
Посмотреть как будет выполняться скрипт
$ bash -x script.sh
Исправление ошибок в последней команде
$ cat /proc/cupinfo
cat: /proc/cupinfo: No such file or directory
$ ^cup^cpu
Использование булевых операторов в выражении
if [ 2 -lt 3 ]
then echo "Numbers are still good!"
fi
if [[ 2 < 3 ]]
then echo "Numbers are still good!"
fi
Проверить синтаксис скрипта без его выполнения
$ bash -n script.sh
Подсчёт времени потраченного на выполнение
$ SECONDS=0; sleep 5 ; echo "that took approximately $SECONDS seconds"
Использование арифметики
if [[ $((2+1)) = $((1+2)) ]]
then echo "still ok"
fi
[lsc@home]$ export PROMPT_COMMAND="date"
Fri Jun 5 15:19:18 BST 2009
[lsc@home]$ ls
file_a file_b file_c
Fri Jun 5 15:19:19 BST 2009
[lsc@home]$ ls
Редактировать текущую команду в редакторе
$ ls -l <ctrl+x><ctrl+e>
Поместить курсор в начало/конец строки
Ctrl + a / Ctrl + e
Поменять местами текущий и предыдущий символ/слово
Ctrl + t / Alt + t
Поменять в верхний/нижний регистр всё от текущей
позиции до конца слова
Alt + u / Alt + l
Отчистить файл
$ > file
Использование базовых математических операций.
$ A=10
$ let B="A * 10 + 1" # B=101
$ let B="B / 8" # B=12
$ let B="(RANDOM % 6) + 1" # B от 1 до 6
Первая команда удаляет из истории баша все дубликаты Вторая увеличивает объём истории
$ export HISTCONTROL=erasedups
$ export HISTSIZE=1000
Вырубать баш после 15 минут простоя
$ export TMOUT=$((15*60))
Раскрыть подстановки в выражениях
$ rm -r source/d*.c <Alt + *>
$ rm -r source/delete_me.c source/do_not_delete_me.c
Развернуть переменные и алиасы
$ ls $HOME/tmp <Ctrl Alt + e>
$ ls -N --color=tty -T 0 /home/cramey
Вызывать команды из команд.
$ hostname && dig +short $(hostname) && dig +short -x $(dig +short $(hostname))
Вызывать переменные-переменные
$ foo=bar
$ baz=foo
$ echo ${!baz}
bar
Массивы
array[0]=тест1
array[1]=тест2
echo ${#array[0]} # Длина первого элемента массива
echo ${#array[*]} # Число элементов в массиве
echo ${#array[@]} # Число элементов в массиве
echo ${array[@]:0} # Все элементы массива
echo ${array[@]:1} # Все эелементы массива, начиная со 2-го
area=( ноль один два три четыре )
a=( '' ) # "a" имеет один пустой элемент
hash=( [0]="первый" [1]="второй" [3]="четвертый" )
Элементы массива разделяются пробелами Для обработки строк, как элементов массива нужно на время изменить разделитель:
LD_IFS="$IFS"
IFS=$'\n'
declare -a a
a=( $(cat "file.txt") )
echo "Total:" ${#a[@]}
for i in "${a[@]}"
do
echo "$i"
done
IFS="$OLD_IFS"
Арифметические операторы
+ сложение
- вычитание
* умножение
/ деление
** возведение в степень
% модуль, остаток от деления
+=
-=
/=
*=
%=
Битовые операторы
<< сдвигает на 1 бит влево (умножение на 2)
<<= сдвиг-влево-равно
>> сдвиг вправо на 1 бит (деление на 2)
>>= сдвиг-вправо-равно (имеет смысл обратный <<=)
& по-битовое И (AND)
&= по-битовое И-равно
| по-битовое ИЛИ (OR)
|= по-битовое ИЛИ-равно
~ по-битовая инверсия
! по-битовое отрицание
^ по-битовое ИСКЛЮЧАЮЩЕЕ ИЛИ (XOR)
^= по-битовое ИСКЛЮЧАЮЩЕЕ-ИЛИ-равно
Логические операторы
&& логическое И (and)
|| логическое ИЛИ (or)
Длина строки
${#string}
expr length $string
expr "$string" : '.*'
Длина подстроки в строке
expr match "$string" '$regsubstring'
expr "$string" : '$regsubstring'
Специальные переменные
$# количество аргументов командной строки
$* и $@ содержат все аргументы командной строки
$0 $1 $2 ${10} позиционные параметры
$? код завершения последней выполненной команды, функции или сценария
$$ id процесса
$! pid последнего, запущенного в фоне, процесса
$_ последний аргумент предыдущей команды
Перенаправление вывода
COMMAND_OUTPUT > # Перенаправление stdout (вывода) в файл.
: > filename # Операция > усекает файл "filename" до нулевой длины
# (аналог команды touch)
> filename # Операция > усекает файл "filename" до нулевой длины
COMMAND_OUTPUT >> # Перенаправление stdout (вывода) в файл в режиме добавления
1>filename # Перенаправление вывода (stdout) в файл "filename"
1>>filename # Перенаправление вывода (stdout) в файл "filename", добавление
2>filename # Перенаправление stderr в файл "filename"
2>>filename # Перенаправление stderr в файл "filename", добавление
&>filename # Перенаправление stdout и stderr в файл "filename"
2>&1 # Перенаправляется stderr на stdout
i>&j # Перенаправляется файл с дескриптором i в j
>&j # Перенаправляется файл с дескриптором 1 (stdout)
# в файл с дескриптором j
0< FILENAME # Ввод из файла
< FILENAME # Ввод из файла
Подавить весь вывод программы
find / > /dev/null 2>&1
Получить расширение файла
ext=${file_name##*.}
name=${file_name%.*}
Обрезать пробелы в начале и конце строки
trim() { echo $1; }
echo ">>$(trim 'right side ')<<"
echo ">>$(trim ' left side')<<"
echo ">>$(trim ' both sides ')<<"
>>right side<<
>>left side<<
>>both sides<<
Создать пустой файл или отчистить его содержимое
$ > file.txt
Выбрать все файлы кроме тех что подходят под шаблон
$ shopt extglob
extglob off
$ ls
abar afoo bbar bfoo
$ ls !(b*)
-bash: !: event not found
$ shopt -s extglob #Enables extglob
$ ls !(b*)
abar afoo
$ ls !(a*)
bbar bfoo
$ ls !(*foo)
abar bbar
Итерация по переданным аргументам
for var in "$@"
do
echo "$var"
done
Сопоставляем переменную с шаблоном
if expr "$projectdesc" : "Unnamed repository.*$" >/dev/null
then
projectdesc="UNNAMED PROJECT"
fi
Автоинкремент в bash
$ i=1
$ i=$[i+1]
$ echo $i
2
Заменить все вхождения слова в предыдущей команде и выполнить её
$ echo one two one three one one
one two one three one one
$ !!:gs/one/1
echo 1 two 1 three 1 1
1 two 1 three 1 1
Проверяем колличество переданных аргументов
EXPECTED_ARGS=1
E_BADARGS=65
if [ $# -ne $EXPECTED_ARGS ]
then
echo "Usage: `basename $0` {arg}"
exit $E_BADARGS
fi
- 1 - kvz.io
- 4 - stackoverflow.com
- 5-33 - stackoverflow.com
- 34-42 - user.su
- 44 - www.jasny.net
- 45 - stackoverflow.com
- 47 - stackoverflow.com
- 48 - stackoverflow.com
- 49 - github.com
- 52 - www.linuxweblog.com