Bash скрипты

Матеріал з Wiki.Zina
Версія від 14:14, 25 березня 2022, створена >Zina (→Заменить)
(різн.) ← Попередня версія | Поточна версія (різн.) | Новіша версія → (різн.)
Перейти до навігації Перейти до пошуку

Основное

[ред. | ред. код]

Правила по написанию кода Bash скриптов описаны в руководствах Google Shell Style Guide и Apple Developer Shell Scripting Primer. Вкратце:

  • В начале файла скрипта должна быть строка #!/bin/bash
  • Отступы — 2 пробела.
  • Комментарии отмечаются символом #
  • Команды Bash вводятся каждая на отдельной строке или разделяются символом ;. Исключение составляют конвейеры: в них команды находятся в пределах одной строки и разделены символом |. При этом нужно понимать, что есть команды Bash и есть команды операционной системы. Например, echo — это команда операционной системы, а let — команда Bash.

Вывод строк

[ред. | ред. код]

Перевод строки

[ред. | ред. код]

Символ \n позволяет добавить в строку перевод строки, как будто была нажата клавиша Enter.

Для использования управляющих символов с обратным слэшем (escape sequences, см. ниже в разделе «Цвет») нужно в команду echo добавлять аргумент -e:

echo -e "\nСтрока, перед которой стоит перевод строки."
read -p $'\n'"Вопрос к пользователю, перед которым стоит перевод строки. [Y/n] "
read -p "Вопрос к пользователю, разбитый на две строки."$'\n'"Вы уверены, что хотите это сделать? [Y/n] "

Команда echo по умолчанию добавляет в конец строки перевод строки. Чтобы его убрать, используйте параметр -n:

echo -n "Строка, после которой не будет перевода строки."

Выбор строк из файла

[ред. | ред. код]
head -5 ${FILE} # Первые 5 строк
tail -5 ${FILE} # Последние 5 строк
tail -5 ${FILE} | tac # Последние 5 строк и отсортировать в обратном порядке

Добавить в массив незакомментированные строки (без знака # в начале строки):

while read LINE; do
  ARRAY+=("$LINE")
done < <(grep '^[^#]' ${FILE})

Запись строк в файл

[ред. | ред. код]

Дописать в конец файла file.txt строку:

echo "Строка с текстом" >> file.txt

Дописать в конец файла file.txt несколько строк:

cat >>file.txt <<EOF
Первая строка
Вторая строка
Третья строка
EOF

То же самое с помощью sed:

sed -i '$ a \\nПервая строка\nВторая строка\nТретья строка' file.txt

Содержимое файла source.txt дописать в конец файла file.txt:

cat source.txt >> file.txt

Поиск и замена

[ред. | ред. код]

Найти

[ред. | ред. код]

Найти в переменной ${VAR} фрагмент template:

if [[ "${VAR}" =~ "template" ]]; then
  echo "Найдено!"
fi

Проверить, имеет ли переменная ${VAR} значение one или two:

if [[ "${VAR}" =~ ^one$|^two$ ]]; then
  echo "Найдено!"
fi

Найти в файле ${FILE} строку с фрагментом ${TEMPLATE}:

if grep -q "${TEMPLATE}" "${FILE}"; then
  echo "Найдена строка с текстом '${TEMPLATE}'."
else
  echo "Строк с текстом '${TEMPLATE}' не найдено."
fi

Сохранить в переменной ${STRING} строку из файла ${FILE}, содержащую фрагмент ${TEMPLATE}:

STRING=$(grep "${TEMPLATE}" "${FILE}")

Заменить

[ред. | ред. код]

Заменить в переменной ${VAR} фрагмент template на значение переменной ${REPLACE}:

VAR=`echo "${VAR}" | sed 's/^\(.*\)template\(.*\)$/\1'${REPLACE}'\2/'`

где регулярное выражение s/^\(.*\)template\(.*\)$/\1'${REPLACE}'\2/ разбирается следующим образом:

  • s — замена
  • /ищем/заменяем/ — общая структура регулярного выражения
  • ^ — начало строки
  • $ — конец строки
  • (.*) — здесь:
    • . — любые символы, кроме перевода строки;
    • * — в любом количестве;
    • скобки (…) означают, что найденный фрагмент нужно сохранить во временной переменной \1 (а содержимое второго набора скобок будет сохранено в переменной \2 и т.д.)
    • В sed скобки экранируются обратными слэшами, поэтому полная запись получается \(.*\)
  • \1'${REPLACE}'\2 — здесь:
    • \1 — первая временная переменная
    • '${REPLACE}' — внешняя переменная
    • \2 — вторая временная переменная

Для замены в URL или путях к файлам, содержащих слеши /, чтобы не получать из-за слешей ошибку unknown option to `s', можно использовать другой разделитель:

VAR=`echo "${VAR}" | sed 's|^\(.*\)template\(.*\)$|\1'${REPLACE}'\2|'`

Сохранить найденный фрагмент в переменную

[ред. | ред. код]

Чтобы присвоить переменной фрагмент, найденный оператором =~, используем специальную переменную BASH_REMATCH:

if [[ "${VAR}" =~ ^(template).*$ ]]; then
  TEMPLATE=${BASH_REMATCH[1]}
fi

Trim — удалить пробелы в начале и в конце переменной

[ред. | ред. код]
VAR="$(echo -e "${VAR}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"

Сделать первую букву слова заглавной или строчной

[ред. | ред. код]

Специальная последовательность \u переводит следующий за ней один символ в верхний регистр.

Аналогичная последовательность \l переводит один следующий символ в нижний регистр.

Последовательности \U или \L переводят все символы в верхний и нижний регистр, пока не встретится \E или не закончится строка подстановки.

# Сделать первую букву слова заглавной:
# WORD=`upfirst ${WORD}`
upfirst() {
  echo -n ${1:0:1} | sed 's/[[:lower:]]/\u&/g'
  echo ${1:1}
}

# Сделать первую букву слова строчной:
# WORD=`lowfirst ${WORD}`
lowfirst() {
  echo -n ${1:0:1} | sed 's/[[:upper:]]/\l&/g'
  echo ${1:1}
}

Манипуляции с переменными

[ред. | ред. код]

http://freaksidea.com/show-39-uchimsia-proghrammirovat-v-shell-manipuliatsii-s-peremennymi

Конкатенация переменной:

second=$first' is a var'

Арифметические операции

[ред. | ред. код]
let "c=a+b" # Сложение
let "a+=b"  # Эквивалентно 'let "a=a+b"'
let "index+=1"

Увеличение значения счетчика на единицу:

((i++))
i=$(($i+1))
let "i+=1"

Сравнение целых чисел

[ред. | ред. код]
[ "$a" -eq "$b" ]  && echo "$a равно $b"
[ "$a" -ne "$b" ]  && echo "$a не равно $b"

[ "$a" -gt "$b" ]  && echo "$a больше, чем $b"
(( "$a" > "$b" ))  && echo "$a больше, чем $b"

[ "$a" -ge "$b" ]  && echo "$a больше или равно $b"
(( "$a" >= "$b" )) && echo "$a больше или равно $b"

[ "$a" -lt "$b" ]  && echo "$a меньше, чем $b"
(( "$a" < "$b" ))  && echo "$a меньше, чем $b"

[ "$a" -le "$b" ]  && echo "$a меньше или равно $b"
(( "$a" <= "$b" )) && echo "$a меньше или равно $b"

Сравнение строк

[ред. | ред. код]
[ "$a" = "$b" ]  && echo "$a равно $b"
[ "$a" == "$b" ] && echo "$a равно $b"

== является синонимом оператора =.

[[ $a == z* ]]    # истина, если $a начинается с символа "z" (сравнение по шаблону)
[[ $a == "z*" ]]  # истина, если $a равна z*
[ "$a" == "z*" ]  # истина, если $a равна z*
[ $a == z* ]      # подстановка имен файлов и разбиение на слова
[ "$a" != "$b" ]  && echo "$a не равно $b"
[ "$a" == "$b" ]  && echo "$a равно $b"

[[ "$a" < "$b" ]] && echo "$a меньше, чем $b (в смысле величины ASCII-кодов)"
[ "$a" \< "$b" ]  && echo "$a меньше, чем $b (в смысле величины ASCII-кодов)"

[[ "$a" > "$b" ]] && echo "$a больше, чем $b (в смысле величины ASCII-кодов)"
[ "$a" \> "$b" ]  && echo "$a больше, чем $b (в смысле величины ASCII-кодов)"

Обратите внимание! Символы < и > необходимо экранировать внутри одинарных квадратных скобок [ ].

Разыменование переменной

[ред. | ред. код]

Функция, которая получает в качестве аргумента имя переменной и выводит на экран и имя переменной и её значение:

variable() {
  local NAME=$1
  local VALUE=$(eval 'echo -n "$'${NAME}'"')
  echo "${NAME} = '${VALUE}'"
}

Проверка

[ред. | ред. код]

Код возврата

[ред. | ред. код]

$? — специальная переменная, в которой хранится код возврата последней команды. По-английски называется exit code или exit status.

Если код возврата равен 0, то команда выполнена успешна. Любые другие значения указывают на какую-то ошибку.

Примеры кодов ошибок:

  • 1: общие ошибки;
  • 2: ошибки работы встроенных средств оболочки;
  • 126: невозможно вызвать запрошенную команду;
  • 127: команда не найдена;
  • 128: некорректный аргумент exit;
  • 128 + n: сигнал критической ошибки (например, kill -9 = 137);
  • 130: скрипт прерван по Ctrl+C.

Пример использования кода возврата:

mkdir /usr
if [ $? -ne 0 ] ; then
  echo "\$? = $?"
  echo "mkdir /usr failed: we have an exit code of $?"
else
  echo "\$? = $?"
  echo "made the requested directory. Why is '/' world writable?"
fi

Из-за того, что каждая следующая команда (даже echo) перезаписывает переменную $?, иногда полезно сразу сохранить ее значение в собственную переменную:

mkdir /usr
status=$?
if [ $status -ne 0 ] ; then
  echo "mkdir /usr failed: we have an exit code of $status"
fi

Или использовать собственную функцию:

# Use: test command
test() {
  "$@"
  local status=$?
  if [ $status -ne 0 ]; then
    echo "error with $1" >&2
  fi
  return $status
}

Проверка существования программы или команды

[ред. | ред. код]
command -v vim

Проверка переменных

[ред. | ред. код]

-z ${VAR+x} — переменная $VAR не определена (подробнее):

if [ -z ${VAR+x} ]; then 
  echo "VAR не определена"
else
  echo "VAR определена как '$VAR'"
fi

-z — переменная пуста:

[ -z "${VAR}" ] && echo "Переменная VAR пуста"

-n — переменная имеет значение:

[ -n "${VAR}" ] && echo "Переменная VAR имеет значение '${VAR}'"

Проверка массива

[ред. | ред. код]
[ "${#ARRAY[@]}" -eq 0 ] && echo "Массив ARRAY пуст"

Проверка результата команды

[ред. | ред. код]
if drush status | grep -q Connected; then
  echo "Подключение к базе данных есть"
fi

Работа с файлами и папками

[ред. | ред. код]
echo "PWD = ${PWD}" # полный путь к текущему рабочему каталогу
echo "OLDPWD = ${OLDPWD}" # предыдущий рабочий каталог
echo "CDPATH = ${CDPATH}" # пути поиска каталога (используется при вводе команды cd имя_каталога без слэша)
echo "HOME = ${HOME}" # путь к домашнему каталогу пользователя
echo "PATH = ${PATH}" # список каталогов для поиска команд и приложений, когда полный путь к файлу не задан
echo "DIRSTACK = ${DIRSTACK}" # содержимое вершины стека каталогов (который управляется командами pushd и popd)

Получить имя файла из полного пути

[ред. | ред. код]
FILE_PATH="/path/to/file.txt" # Полный путь к файлу
DIR_PATH=$(dirname "${VAR}") # Путь к файлу: "/path/to"
FILENAME_EXT=$(basename "${FILE_PATH}") # Имя файла с расширением: "file.txt"
FILENAME=$(basename "${FILE_PATH}" .txt) # Имя файла без расширения: "file"
EXTENSION="${FILENAME_EXT##*.}" # Расширение: "txt"

Подробнее: Extract filename and extension in Bash

Получить список директорий

[ред. | ред. код]
while read DIR; do
  echo "$DIR"
done < <(ls -d */ | sed 's|/||g')

Проверка папок и файлов

[ред. | ред. код]

-e — файл существует
-f — обычный файл (не каталог и не файл устройства)
-s — файл существует и его размер больше нуля
-d — каталог
-h — символическая ссылка
-L — символическая ссылкой
-r — доступен для чтения (пользователю, запустившему сценарий)
-w — доступен для записи (пользователю, запустившему сценарий)
-x — доступен для исполнения (пользователю, запустившему сценарий)
-b — блочное устройство (floppy, cdrom и т.п.)
-c — символьное устройство (клавиатура, модем, звуковая карта и т.п.)
-p — канал

[ ! -f "$FILE" ] && echo 'Файл не существует'
[ ! -e "$FILE" ] && echo "Файл не найден"
[ ! -d "$DIR" ]  && echo "Папка не существует"
! [[ -d "$DIR" &&  -w "$DIR" ]] && echo "Папка не существует или нет прав для записи"

Альтернативный вариант — с помощью команды ls. Позволяет использовать маску:

if ls ${PATH} 1> /dev/null 2>&1; then
  echo "Папка ${PATH} существует."
else
  echo "${PATH} не существует."
fi

Пустая ли папка:

if `ls -A "${PATH}" | wc -l` -eq 0; then 
  echo "Папка ${PATH} пустая."
fi

Количество файлов и папок:

ls -A | wc -l

Получить список только папок:

ls -d */ | sed 's/\///g'

Проверить, есть ли в субдиректории:

if (( "$(ls -la . | grep '^d' | wc -l)" <= 2 )); then
  echo "Субдиректорий нет"
else
  echo "Есть субдиректории"
fi

Временные файлы и папки

[ред. | ред. код]

Создать файл с уникальным именем в папке /tmp и сохранить имя файла в переменной TEMPFILE:

TEMPFILE="$(mktemp)"

Универсальная (будет работать и в Linux и в Mac OS X) команда для создания временной директории с гарантированно уникальным именем и сохранения ее имени в переменной:

TEMPDIR=`mktemp -d 2>/dev/null || mktemp -d -t 'mytmpdir'`

Массивы

[ред. | ред. код]

Определить массив:

ARRAY=()

или

declare -a ARRAY

Добавить элементы в массив

[ред. | ред. код]

Поместить несколько элементов в массив:

ARRAY=(
  "element1"
  "element2"
  "element3"
)

Добавить в массив один элемент:

ARRAY+=("element4")

Добавить в массив элемент с ключом 0 (т.е. поставить его в начало массива):

ARRAY[0]='element1'

Поместить в массив список файлов (т.е. вывод команды ls):

ARRAY=(`ls`)

То же самое по одному элементу:

i=0
while read line; do
  ARRAY[$i]="$line"
  ((i++))
done < <(ls)

Поместить в массив строки из файла — то же самое, но последняя строка:

done < filename

Вывести элементы массива

[ред. | ред. код]

Показать все элементы массива в строку:

echo "${ARRAY[@]}"

Показать все элементы массива в столбик:

for ELEMENT in "${ARRAY[@]}"; do
  echo "${ELEMENT}"
done

Или с нумерацией (при выводе нумерации увеличиваем каждый номер на единицу, чтобы начинать не с нуля):

for ((i=0; i < ${#ARRAY[*]}; i++)); do
  n=$(($i+1))
  echo "$n. ${ARRAY[$i]}"
done

Показать первый элемент:

echo "${ARRAY[0]}"

Показать последний элемент:

echo "${ARRAY[-1]}" # Не работает в Mac OS X
echo "${ARRAY[*]: -1}"

Количество элементов в массиве

[ред. | ред. код]

Проверить, массив пустой или содержит элементы:

if [ "${#ARRAY[@]}" -eq 0 ]; then
  echo "Массив пустой"
else
  echo "В массиве ${#ARRAY[@]} элементов"
fi

Проверка наличия элемента в массиве

[ред. | ред. код]
# Usage: 'element_exists array element'
# Возвращает 1, если элемент существует.
element_exists() {
  # Массив, в котором проверяем наличие элемента
  declare -a ARRAY=("${!1}")
  # Элемент, который ищем в массиве
  ARRAY_ELEMENT=$2
  for i in ${ARRAY[@]}; do
    if [[ "${i}" == "${ARRAY_ELEMENT}" ]]; then
      return 1
      break
    fi
  done
  return 0
}

Функции

[ред. | ред. код]

Проверка существования функции

[ред. | ред. код]

Выполнить функцию foo только в том случае, если она существует:

declare -F foo &>/dev/null && foo

Специальные переменные аргументов

[ред. | ред. код]
echo "Количество аргументов: $#"
args=$#
echo "Последний аргумент: ${!args}"
# Обратите внимание: ${!$#} — неприменимо.
echo "Все аргументы в виде одной строки: $*"
echo "Все аргументы в виде набора строк: $@"
# $@ — то же самое, что и $*, но при этом каждый параметр представлен как отдельная строка (слово), 
# т.е. параметры не подвергаются какой-либо интерпретации.

Удаление первого аргумента:

shift

Перебор всех аргументов в цикле

[ред. | ред. код]
index=1
for arg in "$@"; do
  echo "Аргумент $index: $arg"
  let "index+=1"
done

Пример функции с аргументами

[ред. | ред. код]
testfun() {
  echo "Аргумент №1: \$1 = $1"
  echo "\$* — все аргументы в виде одной строки: $*"
  echo "\$@ — все аргументы в виде набора строк: $@"
  echo "В переменной \"\$*\" список аргументов хранится как одна строка:"
  index=1
  for arg in "$*"; do  # Обязательно заключать "$*" в кавычки
    echo "Аргумент $index: $arg"
    let "index+=1"
  done
  echo "В переменной \"\$@\" список аргументов хранится как набор строк:"
  index=1
  for arg in "$@"; do
    echo "Аргумент $index: $arg"
    let "index+=1"
  done
}

Запуск функции:

testfun один два три четыре

Результат:

Аргумент $1: один
$@: один два три четыре
$*: один два три четыре

В переменной "$*" список аргументов хранится как одна строка:
Аргумент 1: один два три четыре

В переменной "$@" список аргументов хранится как набор строк:
Аргумент 1: один
Аргумент 2: два
Аргумент 3: три
Аргумент 4: четыре

Передать массив в функцию

[ред. | ред. код]
# Функция, которая выводит список элементов массива, полученного в виде аргумента:
foo() {
  # Поместим все аргументы в один массив ARG_ARRAY:
  local ARG_ARRAY=("$@")
  # Выведем элементы массива ARG_ARRAY в строку:
  echo -e "\nМассив в строку:\n"
  echo "${ARG_ARRAY[@]}"
  # Выведем элементы массива ARG_ARRAY в столбик с нумерацией:
  echo -e "\nМассив в столбик:\n"
  n=1
  for ELEMENT in "${ARG_ARRAY[@]}"; do
    echo "$n) $ELEMENT"
    ((n++))
  done
  # Выведем отдельные элементы массива ARG_ARRAY:
  echo -e "\n\${ARG_ARRAY[0]} - Элемент 1: ${ARG_ARRAY[0]}"
  echo -e "\${ARG_ARRAY[1]} - Элемент 2: ${ARG_ARRAY[1]}"
  echo -e "\${ARG_ARRAY[-1]} - Последний элемент: ${ARG_ARRAY[-1]}"
}

# Добавим в массив элементы:
ARRAY=(
  "element1"
  "element2"
)
# Переменная:
VAR="element3.1 element3.2"

# Передаем массив, переменную и пару простых аргументов в функцию:
foo "${ARRAY[@]}" "$VAR" "element4" "element5.1 element5.2"

Проверить, содержит аргумент 1 элемент или массив

[ред. | ред. код]
declare -a ARGUMENT=("${!1}")
COUNT=${#ARGUMENT[@]}
if [[ "${COUNT}" == 1 ]]; then
  echo "В \$1 находится одна переменная: '$1'"
else
  echo "В \$1 находится массив из ${COUNT} переменных:"
  for ((a=0; a < ${#ARGUMENT[*]}; a++)); do
    echo " - ${ARGUMENT[$a]}"
  done
fi

Чтение ввода (строка приглашения, prompt)

[ред. | ред. код]

С чистым полем ввода:

read -p "Домен сайта: "

С возможностью редактирования подставленного по умолчанию текста:

DOMAIN="example.com"
read -e -p "Домен сайта: " -i "${DOMAIN}"

Срабатывание после нажатия одной клавиши:

while true; do
  read -p "Вы уверены, что хотите сделать это? [y/n] " CASE
  case ${CASE} in
    [YyДд]*) echo "Да, сделаем это!"; break ;;
    [NnНн]*) echo "Ничего не делаем."; break ;;
    *) echo "Пожалуйста, нажмите y или n" ;;
  esac
done

Срабатывание после набора правильного ответа и нажатия Enter — или просто нажатия Enter, что равно выбору варианта по умолчанию (в этом примере помеченного заглавнрй Y):

while true; do
  read -p "Вы уверены, что хотите сделать это? [Y/n] "
  if echo ${REPLY} | grep -qi "^y$\|^yes$\|^д$\|^да$\|^$"; then
    echo "Да, сделаем это!"
    break
  elif echo ${REPLY} | grep -qi "^n$\|^no$\|^н$\|^нет$"; then
    echo "Ничего не делаем."
    break
  else
    echo "Пожалуйста, нажмите y или n"
  fi
done

Алиасы

[ред. | ред. код]

Часто алиасы по умолчанию отключены в bash скриптах, и поэтому команды вида alias ll="ls -l" не работают.

Чтобы включить алиасы в Bash скрипте, достаточно добавить в начале скрипта строку:

shopt -s expand_aliases

Алиас на выход из скрипта как в vim:

alias :q='tput setaf 1; echo >&2 "This is NOT vi(m) :/"; tput sgr0'

Конфиги

[ред. | ред. код]

User Interface

[ред. | ред. код]

Сохранить содержимое экрана и очистить его, выполнить работу, выждать 5 секунд и затем восстановить сохраненный экран:

tput smcup    # Save the display
echo 'Hello, World!'  # Work hard
sleep 5       # Wait five seconds
tput rmcup    # Restore the display

Перемещение курсора:

tput cup Y X # Переместить курсор в позицию Y X (верхний левый угол: 0 0)
tput sc # Запомнить позицию курсора
tput rc # Восстановить позицию курсора
tput lines # Вывести количество строк на экране терминала
tput cols # Вывести количество колонок на экране терминала
tput cub N # Переместить курсор на N символов влево
tput cuf N # Переместить курсор на N символов вправо
tput cuu N # Вверх на N строк
tput cud N # Вниз на N строк
tput hpa X # Передвинуть курсор в позицию X
$(tput hpa $(tput cols) # Передвинуть курсор в конец строки

Скрыть и снова показать курсор:

tput civis # скрыть курсор
tput cnorm # показать курсор

Очистка:

el # Очистить от курсора до конца строки
el1 # Очистить от курсора до начала строки
ed # Очистить от курсора до конца экрана
clear # Очистить экран и поместить курсор в левый верхний угол

Вывести текст по центру предпоследней строки внизу экрана:

echo_bottom_center() { 
  echo `tput cup $(($(tput lines))) $(( ($(tput cols) - $(echo "${#1}"))/2 ))`"$1"`tput cup $(tput lines) $(( $(tput cols)-1 ))`; 
}
echo_bottom_center "Bottom Center Text."

Вывести текст по центру экрана:

echo_vertical_center() { 
  echo `tput cup $(($(tput lines)/2)) $(( ($(tput cols) - $(echo "${#1}"))/2))`"$1"`tput cup $(tput lines) $(( $(tput cols)-1 ))`; 
}
echo_vertical_center "Vertical Center Text."

Вывести и обновлять время и дату справа внизу:

echo_time() { 
 echo `tput cup $(($(tput lines)-2)) $(($(tput cols)-$(echo ${#1})))&&tput sc`"$1"`tput cup $(($(tput lines)-2)) 0 && tput rc`; 
} 
while [ 1 ]; do 
  echo_time "`date`"
done

Вывести строку из звездочек шириной в экран терминала:

seq -s'*' 0 $(tput cols) | tr -d '[:digit:]'

Еще примеры tput:

Раскраска, цвет, color

[ред. | ред. код]

http://misc.flogisoft.com/bash/tip_colors_and_formatting

Для отображения цветного и выделенного текста в Bash используются escape sequences (эскейп последовательности, управляющие последовательности, экранированные последовательности).

Шаблон управляющей последовательности: <Esc>[FormatCodem

В синтаксисе Bash для обозначения <Esc> можно использовать один из трех вариантов:

  • \e – не работает в Mac OS X
  • \033
  • \x1B

Команда echo по умолчанию не обрабатывает управляющие последовательности. Чтобы включить это, нужно использовать параметр '-e': echo -e.

Для очистки всех атрибутов применяется управляющая последовательность 0 (в полном виде: \e[0m). Имеет смысл ставить ее в конце каждого выделенного текста.

Примеры:

echo -e "Normal \e[1mBold\e[0m" # 1 - Полужирный
echo -e "Normal \e[2mDim\e[0m" # 2 - Приглушенный
echo -e "Normal \e[4mUnderlined\e[0m" # 4 - Подчеркнутый
echo -e "Normal \e[5mBlink\e[0m" # 5 - Мигающий
echo -e "Normal \e[7mInverted\e[0m" # 7 - Инвертированный

Текстовый интерфейс форм с чекбоксами и т.п. Альтернатива для dialog. Не поддерживает мышь и часть виджетов dialog'а, но работает надёжнее без глюков. Также, в отличие от dialog, во многих дистрибутивах устанавливается по умолчанию.

Графический интерфейс, Zenity On Steroids.

Горизонтальные линии

[ред. | ред. код]

http://brettterpstra.com/2015/02/20/shell-trick-printf-rules/

Отладка Bash скриптов

[ред. | ред. код]

Встроенные переменные

[ред. | ред. код]

Получить список всех встроенных переменных:

printenv

Информация о системе

echo "HOSTTYPE=\"${HOSTTYPE}\"" # тип машины
echo "OSTYPE=\"${OSTYPE}\"" # тип операционной системы
echo "HOSTNAME=\"${HOSTNAME}\"" # сетевое имя компьютера
echo "USER=\"${USER}\"" # имя текущего пользователя
echo "UID=\"${UID}\"" # реальный идентификатор (UID) текущего пользователя в соответствии с /etc/passwd,
                      # даже если он временно приобрел права другого пользователя с помощью su.
echo "BASH_VERSION=\"${BASH_VERSION}\"" # полный номер версии Bash
echo "BASH_VERSINFO[0]=\"${BASH_VERSINFO[0]}\"" # мажорный номер версии Bash

Настройки

echo "IFS=\"${IFS}\"" # символы, являющиеся разделителями команд и параметров
                      # (по умолчанию — пробел, табуляция и новая строка)
echo "OPTERR=\"${OPTERR}\"" # если имеет значение 1, bash показывает сообщения об ошибках,
                            # выдаваемые встроенной командой getopts. По умолчанию 1.

Отладка

echo "FUNCNAME=\"${FUNCNAME}\"" # имя массива, содержащего имена всех функций выполняемых в настоящее время.
echo "LINENO=\"${LINENO}\"" # номер строки исполняемого сценария
echo "REPLY=\"${REPLY}\"" # переменная по умолчанию, куда записывается ввод пользователя,
                          # выполненный с помощью команды read, если явно не задана другая переменная.
                          # Также может использоваться в операторе select для построения меню выбора.
echo "SECONDS=\"${SECONDS}\"" # время работы сценария в секундах

trap: ловушки

[ред. | ред. код]

Перехват выхода из скрипта по CtrlC:

trap '' 2 # Сигнал 2 (Ctrl-C) запрещен
trap 2    # Разрешение реакции на Ctrl-C

Пример: по CtrlC сначала выполнить команду echo "Exit" и только потом выйти с кодом 1.

trap 'echo "Exit"; exit 1' 2

while [ $count -lt 10 ]; do
  sleep 1
  (( count++ ))
  echo $count
done

Рекомендации по написанию Bash скриптов

[ред. | ред. код]

Ссылки

[ред. | ред. код]