learning:bash
Различия
Показаны различия между двумя версиями страницы.
learning:bash [29.06.2022 11:21] – [Ответы на разные обращения] viacheslav | learning:bash [30.07.2024 19:21] (текущий) – внешнее изменение 127.0.0.1 | ||
---|---|---|---|
Строка 1: | Строка 1: | ||
+ | ====== Bash ====== | ||
+ | [[https:// | ||
+ | [[https:// | ||
+ | [[https:// | ||
+ | [[https:// | ||
+ | [[https:// | ||
+ | Плагины для VSCode: Remote - SSH (подключиться по ssh на удаленный хост), Bash Run Button (кнопка запуска скрипта из GUI). | ||
+ | ===== Основное ===== | ||
+ | ==== Комментарии ==== | ||
+ | <code bash> | ||
+ | # Shebang (в начале скрипта) | ||
+ | #!/bin/bash | ||
+ | |||
+ | # Комментарий | ||
+ | : ' | ||
+ | Комментарий | ||
+ | в несколько строк | ||
+ | ' | ||
+ | </ | ||
+ | |||
+ | ==== Переменные ==== | ||
+ | <code bash> | ||
+ | # Переменные | ||
+ | declare -r pwdfile=/ | ||
+ | pwdfile=/ | ||
+ | declare -l str=" | ||
+ | declare -u str=" | ||
+ | # Quoting a variable preserves whitespace | ||
+ | hello=" | ||
+ | echo $hello | ||
+ | echo " | ||
+ | |||
+ | # Переменные окружения (должна быть в ВЕРХНЕМ_РЕГИСТРЕ) | ||
+ | set # вывести все переменные | ||
+ | export FLOWER=" | ||
+ | unset FLOWER # убрать переменную | ||
+ | |||
+ | # В рамках скрипта все переменные по умолчанию глобальные - они будут действовать и в функциях, | ||
+ | |||
+ | # Подставить значение (здесь: | ||
+ | echo "my variable contains ${MY_VAR: | ||
+ | </ | ||
+ | |||
+ | ==== Алиасы ==== | ||
+ | <code bash> | ||
+ | # Алиас | ||
+ | alias showlog=" | ||
+ | alias showlog # посмотреть команду алиаса showlog | ||
+ | |||
+ | # Чтобы алиас или переменная окружения работали всегда для конкретного пользователя, | ||
+ | # Глобальные настройки для всех пользователей - /etc/bashrc (для функций и алиасов) или / | ||
+ | </ | ||
+ | |||
+ | ==== Математические операции ==== | ||
+ | '' | ||
+ | Чтобы выражение занести в переменную, | ||
+ | |||
+ | |Степень |'' | ||
+ | |Умножение |'' | ||
+ | |Деление |'' | ||
+ | |Деление с остатком (modulo) |'' | ||
+ | |Сложение |'' | ||
+ | |Вычитание |'' | ||
+ | |||
+ | <code bash> | ||
+ | a=4 | ||
+ | b=$((a+2)) # 6 | ||
+ | ((b++)) # 7 | ||
+ | ((b--)) # 6 | ||
+ | ((b*=5)) # 65 | ||
+ | ((b+=5)) # 70 | ||
+ | ((b/=10)) # 7 | ||
+ | ((b-=2)) # 5 | ||
+ | |||
+ | echo $((10/3)) # 3, т. к. bash работает только с целыми числами | ||
+ | echo 10/3 |bc -l # для работы с дробями нужно привлекать bc | ||
+ | </ | ||
+ | |||
+ | ==== Сравнение ==== | ||
+ | '' | ||
+ | ^ ^Для сравнения строк ^Для сравнения чисел ^ | ||
+ | |Меньше |'' | ||
+ | |Больше |'' | ||
+ | |Меньше или равно|'' | ||
+ | |Больше или равно |'' | ||
+ | |Равно |'' | ||
+ | |Не равно |'' | ||
+ | |||
+ | ^ Логические операторы | ||
+ | | И |'' | ||
+ | | ИЛИ |'' | ||
+ | | НЕ |'' | ||
+ | | Ноль? |'' | ||
+ | | Не ноль? |'' | ||
+ | |||
+ | ==== Строки ==== | ||
+ | <code bash> | ||
+ | a=" | ||
+ | b=" | ||
+ | c="$a $b" # Объединение строк | ||
+ | echo $c | ||
+ | hello world | ||
+ | echo ${#c} # длина строки | ||
+ | 11 | ||
+ | echo ${c:3} # начать вывод с 4-го символа (нумерация начинается с 0) | ||
+ | lo world | ||
+ | echo ${c:3:5} # 5 символов после начала вывода | ||
+ | lo wo | ||
+ | echo ${c: -4} # вывод с конца | ||
+ | orld | ||
+ | echo ${c: -4:3} # 3 из 4-х последних | ||
+ | orl | ||
+ | fruits=" | ||
+ | echo ${fruits/ | ||
+ | apple cherry banana banana banana pear | ||
+ | echo ${fruits// | ||
+ | apple cherry cherry cherry cherry pear | ||
+ | echo ${fruits/# | ||
+ | cherry banana banana banana banana pear | ||
+ | echo ${fruits/ | ||
+ | apple banana banana banana banana cherry | ||
+ | echo ${fruits/ | ||
+ | apple cherry | ||
+ | </ | ||
+ | https:// | ||
+ | ==== Heredoc ==== | ||
+ | Heredoc - when you need to pass a multiline block of text or code to an interactive command, such as tee, cat or sftp\\ | ||
+ | https:// | ||
+ | <code bash> | ||
+ | cat << EOF | ||
+ | Hello | ||
+ | Good bye | ||
+ | EOF | ||
+ | |||
+ | # <<- убирает знаки табуляции из начала строк | ||
+ | ftp -n <<- EOF | ||
+ | open mirrors.xmission.com | ||
+ | user anonymous nothinghere | ||
+ | ascii | ||
+ | cd gutenberg | ||
+ | get GUTINDEX.00 | ||
+ | bye | ||
+ | EOF | ||
+ | </ | ||
+ | |||
+ | ==== Цвета ==== | ||
+ | === echo -e === | ||
+ | Есть стандартный довольно замысловатый синтаксис.\\ | ||
+ | Используется '' | ||
+ | Для того, чтобы сбросить настройки в конце текста, | ||
+ | <code bash> | ||
+ | echo -e " | ||
+ | </ | ||
+ | |||
+ | <WRAP group> | ||
+ | <WRAP half column> | ||
+ | ^Color ^Foreground Code ^Background Code ^ | ||
+ | |Black |30 |40 | | ||
+ | |Red |31 |41 | | ||
+ | |Green |32 |42 | | ||
+ | |Yellow |33 |43 | | ||
+ | |Blue |34 |44 | | ||
+ | |Magenta |35 |45 | | ||
+ | |Cyan |36 |46 | | ||
+ | |Light Gray |37 |47 | | ||
+ | |Gray |90 |100 | | ||
+ | |Light Red |91 |101 | | ||
+ | |Light Green |92 |102 | | ||
+ | |Light Yellow |93 |103 | | ||
+ | |Light Blue |94 |104 | | ||
+ | |Light Magenta |95 |105 | | ||
+ | |Light Cyan |96 |106 | | ||
+ | |White |97 |107 | | ||
+ | </ | ||
+ | |||
+ | <WRAP half column> | ||
+ | ^Code ^Description ^ | ||
+ | |0 |Reset/ | ||
+ | |1 |Bold text | | ||
+ | |2 |Faint text (бледный) | | ||
+ | |3 |Italics | | ||
+ | |4 |Underlined text | | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | === tput === | ||
+ | Есть вариант использования tput. | ||
+ | <code bash> | ||
+ | echo -e $(tput setaf 7; tput setab 1; tput blink)" | ||
+ | |||
+ | # Все варианты | ||
+ | for fg_color in {0..7}; do | ||
+ | set_foreground=$(tput setaf $fg_color) | ||
+ | for bg_color in {0..7}; do | ||
+ | set_background=$(tput setab $bg_color) | ||
+ | echo -n $set_background$set_foreground | ||
+ | printf ' F:%s B:%s ' $fg_color $bg_color | ||
+ | done | ||
+ | echo $(tput sgr0) | ||
+ | done | ||
+ | </ | ||
+ | {{: | ||
+ | |||
+ | ^Value ^Color ^ | ||
+ | |0 |Black | | ||
+ | |1 |Red | | ||
+ | |2 |Green | | ||
+ | |3 |Yellow | | ||
+ | |4 |Blue | | ||
+ | |5 |Magenta | | ||
+ | |6 |Cyan | | ||
+ | |7 |White | | ||
+ | |8 |Not used | | ||
+ | |9 |Reset to default color | | ||
+ | |||
+ | https:// | ||
+ | |||
+ | ==== Классы символов ==== | ||
+ | ^POSIX class ^Equivalent to ^Matches ^ | ||
+ | |'' | ||
+ | |'' | ||
+ | |'' | ||
+ | |'' | ||
+ | |'' | ||
+ | |'' | ||
+ | |'' | ||
+ | |'' | ||
+ | |'' | ||
+ | |'' | ||
+ | |'' | ||
+ | |'' | ||
+ | |'' | ||
+ | |'' | ||
+ | |||
+ | Примеры | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | https:// | ||
+ | |||
+ | ==== Прочее ==== | ||
+ | |||
+ | === Посылка данных в другой скрипт === | ||
+ | <code bash> | ||
+ | # first.sh | ||
+ | MESSAGE=" | ||
+ | export MESSAGE | ||
+ | ./second.sh | ||
+ | # second.sh | ||
+ | echo "The message is: $MESSAGE" | ||
+ | # Теперь при вызове ./first.sh будет показываться сообщение The message is: Hello there | ||
+ | </ | ||
+ | |||
+ | === Изменение строки запроса консоли === | ||
+ | Для этого можно менять переменные окружения PS | ||
+ | <code bash> | ||
+ | set |egrep ^PS | ||
+ | PS1=' | ||
+ | PS2='> | ||
+ | PS4='+ ' | ||
+ | |||
+ | export PS1='[ \u @ \w ]> ' | ||
+ | # Есть разные параметры - \d (date), \t (time), \j (jobs), \h (hostname), \w (current dir) и т. д. | ||
+ | </ | ||
+ | |||
+ | <code bash> | ||
+ | # История (файл - ~/ | ||
+ | history -cw # очистить и записать файл | ||
+ | |||
+ | # Скрипт - в начале нужно вставлять строку (# необходим в начале строки): | ||
+ | #!/bin/bash | ||
+ | |||
+ | which cp # выводит полный путь к команде (программе), | ||
+ | whereis cp # выводит пути к бинарнику команды/ | ||
+ | locate kernel # быстрый поиск путей, содержащих слово kernel. Gрограмма locate может быть не установлена (apt install plocate). | ||
+ | updatedb # обновление базы locate, чтобы она увидела только что созданные файлы (она обновляется по крону) | ||
+ | </ | ||
+ | |||
+ | ===== Сочетания клавиш в консоли ===== | ||
+ | * Ctrl+a - в начало строки | ||
+ | * Ctrl+e - в конец строки | ||
+ | * Ctrl+k - удалить всё от курсора до конца строки | ||
+ | * Ctrl+u - удалить всё от курсора до начала строки | ||
+ | * Ctrl+l - очистить экран, кроме текущей строки | ||
+ | * Ctrl+w - удалить последнее слово (до разделителя-пробела) | ||
+ | * Ctrl+t - тащит символ, | ||
+ | * Ctrl+f - forward, перемещать курсор вперёд по строке (то же, что и ->) | ||
+ | * Ctrl+b - back, перемещать курсор назад по строке (то же, что и <-) | ||
+ | * Ctrl+h - удалить предыдущий символ (как backspace) | ||
+ | * Ctrl+d - удалить следующий символ (как delete) | ||
+ | * Ctrl+p - показать предыдущую команду (то же, что и ↑) | ||
+ | |||
+ | ===== Потоки (stdin, stdout, stderr) и перенаправления ===== | ||
+ | stdout - стандартный вывод. | ||
+ | <code bash> | ||
+ | cat * > file1.txt # Перенаправить stdout (>) в файл | ||
+ | echo " | ||
+ | </ | ||
+ | stderr - вывод ошибок. | ||
+ | <code bash> | ||
+ | ls absentDir > file1.txt # если каталог не существует, | ||
+ | ls absentDir 2> file1.txt # Перенаправление потока ошибок (2>) | ||
+ | ls absentDir 2>> file1.txt # Перенаправление потока ошибок (2>> | ||
+ | ls absentDir 2>> /dev/null # Подавление вывода ошибок | ||
+ | |||
+ | # Комбинированный вывод - содержимое существующих файлов будет в out.txt, а ошибки - в err.txt | ||
+ | cat file1 file2 nofile > out.txt 2> err.txt | ||
+ | # И содержимое, | ||
+ | cat file1 file2 nofile > out.txt 2>&1 | ||
+ | </ | ||
+ | Как сделать, | ||
+ | <code bash> | ||
+ | set -o noclobber # включить опцию в bash | ||
+ | echo " | ||
+ | echo " | ||
+ | set +o noclobber # выключить | ||
+ | </ | ||
+ | |||
+ | ===== Именованный канал (named pipe) ===== | ||
+ | Помимо обычных каналов, | ||
+ | |||
+ | Сиздать именованный канал можно командами '' | ||
+ | <code bash> | ||
+ | mknod metal_pipe p | ||
+ | cat file1 > metal_pipe | ||
+ | # ctrl+c | ||
+ | ls -l metal_pipe | ||
+ | prw-rw----- | ||
+ | </ | ||
+ | ===== Условие ===== | ||
+ | <code bash> | ||
+ | c=1 | ||
+ | if [ $c -eq 1 ] | ||
+ | then | ||
+ | echo "c equals 1" | ||
+ | elif [ $c -lt 1 ] | ||
+ | then | ||
+ | echo "c is less than 1" | ||
+ | else | ||
+ | echo "c is bigger than 1" | ||
+ | fi | ||
+ | # Вместо -eq, -gt и -lt и т. д. можно писать ==, >, <, >= и т. д., но тогда нужны двойные круглые скобки: | ||
+ | if (( $c <= 1 )) | ||
+ | # Оператор " | ||
+ | if [ $c -gt 10 ] && [ $c -lt 30 ] | ||
+ | if [[ $c -gt 10 && $c -lt 30 ]] | ||
+ | if [ $c -gt 10 -a $c -lt 30 ] | ||
+ | # Оператор " | ||
+ | if [ $c -gt 10 ] || [ $c -lt 30 ] | ||
+ | if [[ $c -gt 10 || $c -lt 30 ]] | ||
+ | if [ $c -gt 10 -o $c -lt 30 ] | ||
+ | # match | ||
+ | if [[ $a =~ [0-9]+ ]] # есть ли в строке цифры | ||
+ | |||
+ | # case - типа switch в Powershell (https:// | ||
+ | echo -n "Enter the name of a country: " | ||
+ | read COUNTRY | ||
+ | echo -n "The official language of $COUNTRY is " | ||
+ | case $COUNTRY in | ||
+ | # скобка завершает список паттернов | ||
+ | Lithuania) echo " | ||
+ | Romania | Moldova) echo " | ||
+ | Italy | "San Marino" | ||
+ | *) echo " | ||
+ | esac # завершение case | ||
+ | |||
+ | # Выбор из пунктов | ||
+ | VEGS=(' | ||
+ | select VEG in ${VEGS[@]} | ||
+ | do | ||
+ | case $VEG in | ||
+ | TOMATO | CUCUMBER | ONION | PEASE | RADISH | DILL) | ||
+ | echo " | ||
+ | *) | ||
+ | echo " | ||
+ | esac | ||
+ | done | ||
+ | </ | ||
+ | |||
+ | ===== Циклы ===== | ||
+ | |||
+ | <code bash> | ||
+ | # while | ||
+ | number=1 | ||
+ | while [ $number -le 10 ] | ||
+ | do | ||
+ | echo " | ||
+ | ((number++)) # можно ((number+=1)) | ||
+ | done | ||
+ | |||
+ | # until | ||
+ | number=1 | ||
+ | until [ $number -gt 10 ] | ||
+ | do | ||
+ | echo " | ||
+ | ((number++)) | ||
+ | done | ||
+ | |||
+ | # for | ||
+ | for i in 1 2 3 4 5 # {1..5} или ${array[@]} | ||
+ | do | ||
+ | echo $i | ||
+ | done | ||
+ | # for i in {0..100..5} - c 0 до 100 с шагом 5 | ||
+ | # for c in {01..75}; do echo $c; done; # for two digits | ||
+ | # for c in {001..075}; do echo $c; done; # for three digits | ||
+ | |||
+ | |||
+ | for (( i=0; i<5; i++ )) # (( задать переменную; | ||
+ | do | ||
+ | echo $i | ||
+ | done | ||
+ | |||
+ | # for loop для ассоциированного массива | ||
+ | declare -A array | ||
+ | array[" | ||
+ | array[" | ||
+ | for i in " | ||
+ | do | ||
+ | echo "$i: ${array[$i]}" | ||
+ | done | ||
+ | |||
+ | # прерывание цикла | ||
+ | for (( i=0; i<=10; i++ )) | ||
+ | do | ||
+ | if [ $i -gt 5 ] | ||
+ | then | ||
+ | break # прервать цикл | ||
+ | fi | ||
+ | echo $i | ||
+ | done | ||
+ | |||
+ | # продолжение цикла | ||
+ | for (( i=0; i<=10; i++ )) | ||
+ | do | ||
+ | if [[ $i -eq 3 || $i -eq 7 ]] | ||
+ | then | ||
+ | | ||
+ | fi | ||
+ | echo $i | ||
+ | done | ||
+ | |||
+ | </ | ||
+ | |||
+ | ===== Входные данные ===== | ||
+ | |||
+ | <code bash> | ||
+ | #! /bin/bash | ||
+ | echo $0 $1 $2 $3 | ||
+ | |||
+ | # $0 - имя скрипта | ||
+ | bash test.sh letterA letterB letterC | ||
+ | test.sh letterA letterB letterC | ||
+ | |||
+ | # Вариант входных данных в скрипт через массив | ||
+ | args=(" | ||
+ | echo ${args[0]} ${args[1]} ${args[2]} | ||
+ | |||
+ | args=(" | ||
+ | echo $@ # вывести все элементы массива | ||
+ | echo $# # вывести число элементов в массиве | ||
+ | |||
+ | for i in $@; do | ||
+ | echo $i | ||
+ | done | ||
+ | echo "There are $# arguments." | ||
+ | |||
+ | ./script.sh one two three | ||
+ | one | ||
+ | two | ||
+ | three | ||
+ | There are 3 arguments. | ||
+ | |||
+ | # Ввод данных пользователем при выполнении скрипта | ||
+ | echo " | ||
+ | read name | ||
+ | echo "Enter your password" | ||
+ | read -s pass # выводиться на экран во время ввода не будет | ||
+ | read -p " | ||
+ | |||
+ | echo "Name: $name, Password: $pass, Colour: $colour" | ||
+ | |||
+ | # Выбор из пунктов | ||
+ | select animal in " | ||
+ | do | ||
+ | echo "You selected $animal!" | ||
+ | break | ||
+ | done | ||
+ | |||
+ | 1) cat | ||
+ | 2) dog | ||
+ | 3) bird | ||
+ | 4) fish | ||
+ | #? 4 | ||
+ | You selected fish! | ||
+ | |||
+ | # С выходом | ||
+ | select option in " | ||
+ | do | ||
+ | case $option in | ||
+ | cat) echo "Cats meow";; | ||
+ | dog) echo "Dogs bark";; | ||
+ | quit) break;; | ||
+ | *) echo " | ||
+ | esac | ||
+ | done | ||
+ | |||
+ | </ | ||
+ | |||
+ | ===== Проверки ===== | ||
+ | <code bash> | ||
+ | # Программа работает, | ||
+ | if [ $# -lt 3 ]; then | ||
+ | cat <<- EOF | ||
+ | Three arguments required: | ||
+ | name, id, favourite color. | ||
+ | EOF | ||
+ | else | ||
+ | echo "Name: $1" | ||
+ | echo "ID: $2" | ||
+ | echo " | ||
+ | fi | ||
+ | |||
+ | # Повторение вопроса, | ||
+ | read -p " | ||
+ | while [[ -z " | ||
+ | read -p "Give me an answer! Color? " color | ||
+ | done | ||
+ | echo " | ||
+ | |||
+ | # Ответ по умолчанию, | ||
+ | read -p " | ||
+ | while [[ -z " | ||
+ | color=" | ||
+ | done | ||
+ | echo " | ||
+ | |||
+ | # Принимать ответ только если это 4 цифры, если год после 1980 и он не начинается с нуля | ||
+ | read -p "Year? [4 digits] " y | ||
+ | while [[ ! $y =~ [0-9]{4} ]] || (( $y < 1980 )) || [[ $y =~ ^0 ]]; do | ||
+ | read -p "Wrong format or earlier than 1980! Year? " y | ||
+ | done | ||
+ | echo " | ||
+ | |||
+ | # Игра " | ||
+ | #!/bin/bash | ||
+ | function game { | ||
+ | s=$((1+ $RANDOM % 10)) | ||
+ | read -p " | ||
+ | |||
+ | while [[ $n != $s ]]; do | ||
+ | if [[ ! $n ]]; then | ||
+ | read -p "Вы ничего не ввели, напишите число от 1 до 10: " n | ||
+ | elif [[ ! $n =~ ^[0-9]0?$ ]]; then | ||
+ | read -p "Вы ошиблись в написании числа, попробуйте ещё раз: " n | ||
+ | elif [[ $n -lt 1 || $n -gt 10 ]]; then | ||
+ | read -p "Вы ввели число вне диапазона, | ||
+ | elif [[ $s -gt $n ]]; then | ||
+ | read -p " | ||
+ | elif [[ $s -lt $n ]]; then | ||
+ | read -p " | ||
+ | fi | ||
+ | done | ||
+ | |||
+ | echo " | ||
+ | } | ||
+ | |||
+ | if [[ $1 =~ [Gg][Aa][Mm][Ee] ]]; then | ||
+ | game | ||
+ | else | ||
+ | echo " | ||
+ | fi | ||
+ | |||
+ | Угадайте число от 1 до 10: ыыы | ||
+ | Вы ошиблись в написании числа, попробуйте ещё раз: | ||
+ | Вы ничего не ввели, напишите число от 1 до 10: 0 | ||
+ | Вы ввели число вне диапазона, | ||
+ | Вы ввели число вне диапазона, | ||
+ | Загаданное число больше, | ||
+ | Загаданное число меньше, | ||
+ | Загаданное число меньше, | ||
+ | Загаданное число меньше, | ||
+ | Поздравляю, | ||
+ | </ | ||
+ | |||
+ | ===== Вывод информации ===== | ||
+ | <code bash> | ||
+ | # 1 - standard output, 2 - standard error | ||
+ | ls 1> output.txt 2> errors.txt | ||
+ | ls 2>&1 # перенаправить ошибки в стандартный вывод | ||
+ | </ | ||
+ | |||
+ | ===== Строки ===== | ||
+ | <code bash> | ||
+ | if [ " | ||
+ | if [ " | ||
+ | c=$st1$st2 # concatenation | ||
+ | echo ${st1,,} # to lowercase | ||
+ | echo ${st2^^} # to uppercase | ||
+ | echo ${st1^} # capitalize first letter | ||
+ | </ | ||
+ | |||
+ | ===== Числа ===== | ||
+ | <code bash> | ||
+ | n1=256 | ||
+ | n2=7 | ||
+ | echo $(( n1 % n2 )) # деление с остатком (так же для +, -, *, /) | ||
+ | echo $(expr $n1 + $n2) # вариант через expr (знак умножения надо экранировать - $n1 \* $n2) | ||
+ | echo " | ||
+ | |||
+ | # Арифметическая оценка | ||
+ | ((var = 12 + 7)) # код возврата 0 | ||
+ | # Арифметическая оценка | ||
+ | var=$((12 + 7)) # var=19 | ||
+ | |||
+ | # Префиксный и постфиксный инкремент | ||
+ | var=1 | ||
+ | ((result = ++var)) # result и var равны 2 | ||
+ | ((result = var++)) # result равен 1, var равен 2 | ||
+ | |||
+ | # Тернарный оператор | ||
+ | # Замена конструкции if-then-else | ||
+ | if ((var < 10)) | ||
+ | then | ||
+ | ((result = 0)) | ||
+ | else | ||
+ | ((result = var)) | ||
+ | fi | ||
+ | # на (( УСЛОВИЕ ? ДЕЙСТВИЕ 1 : ДЕЙСТВИЕ 2 )) | ||
+ | ((result = var < 10 ? 0 : var)) | ||
+ | # в bash тернарный оператор можно использовать только в арифм. оценке или подстановке, | ||
+ | </ | ||
+ | ===== Массивы ===== | ||
+ | <code bash> | ||
+ | food=(' | ||
+ | echo " | ||
+ | bread butter cheese juice | ||
+ | echo " | ||
+ | cheese | ||
+ | echo " | ||
+ | juice | ||
+ | echo " | ||
+ | juice | ||
+ | echo " | ||
+ | butter cheese | ||
+ | food[5]=" | ||
+ | food+=(" | ||
+ | echo " | ||
+ | 0 1 2 3 5 6 | ||
+ | echo " | ||
+ | 6 | ||
+ | |||
+ | files=$(ls Documents/ | ||
+ | declare -a files=(Documents/ | ||
+ | files=(Documents/ | ||
+ | |||
+ | # Определение элементов массива по отдельности | ||
+ | doc="/ | ||
+ | files=([0]=" | ||
+ | |||
+ | # Ассоциированные массивы | ||
+ | # Можно задать сразу все элементы | ||
+ | declare -A user=([" | ||
+ | # Можно задать элементы постепенно | ||
+ | declare -A myarray | ||
+ | myarray[size]=big | ||
+ | myarray[room]=" | ||
+ | echo The " | ||
+ | # Содержимое массива | ||
+ | declare -p myarray | ||
+ | declare -A myarray=([room]=" | ||
+ | |||
+ | # Список ключей - ! | ||
+ | echo " | ||
+ | room size | ||
+ | |||
+ | # Удалить массив или элемент | ||
+ | unset myarray | ||
+ | unset myarray[0] | ||
+ | unset myarray[size] | ||
+ | |||
+ | # Текст в массив | ||
+ | mapfile -t names_array < names.txt # синоним команды mapfile - readarray | ||
+ | </ | ||
+ | ===== Функции ===== | ||
+ | Рекомендации: | ||
+ | - Имя функции должно сообщать читателю кода, что она делает. | ||
+ | - В функциях нужно использовать только локальные переменные. В ином случае конфликт имён локальных и глобальных переменных решается соглашением об их именовании. | ||
+ | - Не надо использовать глобальные переменные в функциях. Вместо этого значение глобальной переменной передаётся в функцию через параметр. | ||
+ | - Не надо использовать ключевое слово '' | ||
+ | <code bash> | ||
+ | funcName() { | ||
+ | echo $1 $2 # входные позиционные аргументы | ||
+ | } | ||
+ | funcName "Good morning," | ||
+ | Good morning, man! | ||
+ | |||
+ | # Объявление функции в одну строку | ||
+ | cpuinfo() { cat / | ||
+ | |||
+ | # Удалить функцию, | ||
+ | unset -f cpuinfo | ||
+ | |||
+ | # Все аргументы, | ||
+ | count() { | ||
+ | c=1 | ||
+ | for arg in $@; do | ||
+ | printf " | ||
+ | ((c++)) | ||
+ | done | ||
+ | } | ||
+ | count $(ls) | ||
+ | |||
+ | # Параметры (флаги). | ||
+ | # Двоеточие после параметра значит, | ||
+ | # Если двоеточия нет, то проверяется только наличие параметра. | ||
+ | while getopts u:p:ab option; do | ||
+ | case $option in | ||
+ | u) user=$OPTARG;; | ||
+ | p) pass=$OPTARG;; | ||
+ | a) echo "Got the A parameter";; | ||
+ | b) echo "Got the B parameter";; | ||
+ | ?) echo " | ||
+ | esac | ||
+ | done | ||
+ | |||
+ | echo "User: $user / Pass: $pass" | ||
+ | |||
+ | # Область переменных: | ||
+ | # иначе можно, при наличии одинаковых имён в скрипте и внутри функции, | ||
+ | suncTest() { | ||
+ | i=" | ||
+ | } | ||
+ | i=" | ||
+ | echo $i # script variable | ||
+ | suncTest | ||
+ | echo $i # function variable | ||
+ | |||
+ | suncTest() { | ||
+ | local i=" | ||
+ | echo $i # function variable, | ||
+ | # потому что происходит сокрытие глобальной переменной при объявлении одноимённой локальной. | ||
+ | } | ||
+ | i=" | ||
+ | echo $i # script variable | ||
+ | suncTest | ||
+ | echo $i # script variable - в скрипте осталась глобальная переменная. | ||
+ | |||
+ | # Массивы в функции по умолчанию как раз локальные. Чтобы сделать их глобальными, | ||
+ | test() { | ||
+ | declare -g files=(Documents/ | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===== Файлы, каталоги ===== | ||
+ | <code bash> | ||
+ | mkdir -p / | ||
+ | touch / | ||
+ | |||
+ | # Проверка существования каталога (файла - ключ -f) | ||
+ | if [ -d " | ||
+ | then | ||
+ | echo "$dir exists" | ||
+ | else | ||
+ | echo "$dir doesn' | ||
+ | fi | ||
+ | |||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | https:// | ||
+ | ==== Учётки, | ||
+ | <code bash> | ||
+ | # Посмотреть, | ||
+ | last | ||
+ | </ | ||
+ | |||
+ | ==== Работа с файлами ==== | ||
+ | <code bash> | ||
+ | # Поиск расширений файлов | ||
+ | find . -type f -name ' | ||
+ | </ | ||
+ | |||
+ | ===== Примеры ===== | ||
+ | Если делитель 3,5 или 7, то выводить соответственно Pling, Plang или Plong. Если заданное число-аргумент делится на несколько делителей сразу, Соединять слова. Если заданное число не делится ни на один из делителей, | ||
+ | <code bash> | ||
+ | #!/bin/bash | ||
+ | |||
+ | array[3]=" | ||
+ | array[5]=" | ||
+ | array[7]=" | ||
+ | |||
+ | main() { | ||
+ | for f in " | ||
+ | if ! (( $1 % $f )); then | ||
+ | str+=" | ||
+ | fi | ||
+ | done | ||
+ | echo " | ||
+ | } | ||
+ | |||
+ | result=$(main " | ||
+ | |||
+ | if [ -n " | ||
+ | echo " | ||
+ | else | ||
+ | echo " | ||
+ | fi | ||
+ | </ | ||
+ | |||
+ | ==== Сравнение строк и вывод кол-ва различающихся символов ==== | ||
+ | <code bash> | ||
+ | if [ $# -lt 2 ]; then echo " | ||
+ | if [ ${#1} -ne ${#2} ]; then echo " | ||
+ | |||
+ | for (( c=0; c< | ||
+ | if [[ " | ||
+ | ((d++)) | ||
+ | fi | ||
+ | done | ||
+ | |||
+ | echo " | ||
+ | </ | ||
+ | |||
+ | ==== Акроним из строки ==== | ||
+ | <code bash> | ||
+ | # Ненужное echo: | ||
+ | # array=$(echo " | ||
+ | array=" | ||
+ | |||
+ | for i in ${array[@]}; | ||
+ | declare -u str+=" | ||
+ | done | ||
+ | |||
+ | echo " | ||
+ | </ | ||
+ | |||
+ | ==== Проверка числа, является ли оно числом Армстронга ==== | ||
+ | |||
+ | |||
+ | <code bash> | ||
+ | for (( c=0; c<${#1}; c++ )); do | ||
+ | d=$((d + (${1:$c:1} ** ${#1}))) # $d в выражении не нужен | ||
+ | done | ||
+ | |||
+ | if [[ $d -eq $* ]]; then | ||
+ | echo " | ||
+ | else | ||
+ | echo " | ||
+ | fi | ||
+ | </ | ||
+ | [[https:// | ||
+ | https:// | ||
+ | https:// | ||
+ | |||
+ | ==== Проверка, | ||
+ | <code bash> | ||
+ | # Assigning an array to a string! Assign as array, or use * instead of @ to concatenate. | ||
+ | declare -l str=" | ||
+ | |||
+ | for i in {a..z}; do | ||
+ | # Remove quotes from right-hand side of =~ to match as a regex rather than literally. | ||
+ | if [[ ! " | ||
+ | echo " | ||
+ | exit | ||
+ | fi | ||
+ | done | ||
+ | |||
+ | echo " | ||
+ | </ | ||
+ | |||
+ | ==== Ответы на разные обращения ==== | ||
+ | В конструкции case сверху надо указывать наиболее специфичные конструкции. | ||
+ | <code bash> | ||
+ | shopt -s extglob | ||
+ | |||
+ | str=" | ||
+ | |||
+ | case " | ||
+ | *([^[: | ||
+ | *([^[: | ||
+ | "" | ||
+ | *\?) echo " | ||
+ | *) echo " | ||
+ | esac | ||
+ | |||
+ | </ | ||
+ | В case используются не регулярки, | ||
+ | '' | ||
+ | |||
+ | ==== Вычисление очков по буквам слова ==== | ||
+ | <code bash> | ||
+ | # Quote parameters to tr to prevent glob expansion | ||
+ | # Declare and assign separately to avoid masking return values | ||
+ | # declare -u str=$(echo " | ||
+ | |||
+ | # Don't use [] around ranges in tr, it replaces literal square brackets. | ||
+ | str=$(echo " | ||
+ | num=0 # Условие - ноль тоже нужно вывести, | ||
+ | |||
+ | for (( c=0; c< | ||
+ | case ${str:$c:1} in | ||
+ | A|E|I|O|U|L|N|R|S|T) num=$((num+1));; | ||
+ | D|G) num=$((num+2));; | ||
+ | B|C|M|P) num=$((num+3));; | ||
+ | F|H|V|W|Y) num=$((num+4));; | ||
+ | K) num=$((num+5));; | ||
+ | J|X) num=$((num+8));; | ||
+ | Q|Z) num=$((num+10));; | ||
+ | esac | ||
+ | done | ||
+ | |||
+ | echo " | ||
+ | </ | ||
+ | https:// | ||
+ | https:// | ||
+ | |||
+ | ==== Подсчёт зёрен на клетках шахматной доски ==== | ||
+ | '' | ||
+ | <code bash> | ||
+ | squarecalc() { | ||
+ | # Argument mixes string and array. Use * or separate argument. | ||
+ | bc <<< | ||
+ | } | ||
+ | # Arrays implicitly concatenate in [[ ]]. Use a loop (or explicit * instead of @). | ||
+ | if [[ $@ -ge 1 && $@ -le 64 ]]; then | ||
+ | # Double quote array expansions to avoid re-splitting elements. | ||
+ | # Useless echo? Instead of 'echo $(cmd)', | ||
+ | echo $(squarecalc " | ||
+ | # Arrays implicitly concatenate in [[ ]]. Use a loop (or explicit * instead of @). | ||
+ | elif [[ $@ == " | ||
+ | t=0 | ||
+ | for ((c=1; c<=64; c++)); do | ||
+ | d=$(squarecalc $c) | ||
+ | t=$(bc <<< | ||
+ | done | ||
+ | echo " | ||
+ | else | ||
+ | echo " | ||
+ | exit 1 | ||
+ | fi | ||
+ | </ | ||
+ | https:// | ||
+ | https:// | ||
+ | https:// | ||
+ | https:// | ||
+ | https:// | ||
+ | https:// | ||
+ | |||
+ | ==== Алгоритм Луна (проверка номера кредитки) ==== | ||
+ | <code bash> | ||
+ | check() { | ||
+ | # Идём по знакам по порядку | ||
+ | for ((c=0; | ||
+ | num=${1: | ||
+ | # Если номер знака нечётный (здесь 0 даёт false), то умножаем его на 2, | ||
+ | # $/${} is unnecessary on arithmetic variables. | ||
+ | if ! (($c % 2)); then | ||
+ | num=$((num*2)) | ||
+ | # а если после этого он стал больше 9, вычитаем 9 | ||
+ | if [[ $num -gt 9 ]]; then | ||
+ | num=$((num-9)) | ||
+ | fi | ||
+ | fi | ||
+ | # Добавляем цифру в строку с плюсом | ||
+ | dbl+=" | ||
+ | done | ||
+ | # В конце 0, чтобы строка не заканчивалась плюсом | ||
+ | echo " | ||
+ | } | ||
+ | |||
+ | # Убрать пробелы | ||
+ | cn=" | ||
+ | # Если знаков меньше 2 и есть что-то кроме цифр - выход | ||
+ | # Use -n instead of ! -z. | ||
+ | if [[ " | ||
+ | |||
+ | # Если знаков нечётное кол-во - добавляем 0 в начало | ||
+ | if ((${#cn} % 2)); then | ||
+ | cn=" | ||
+ | terms=$(check " | ||
+ | else | ||
+ | terms=$(check " | ||
+ | fi | ||
+ | |||
+ | # Если сумма знаков кратна 10 (здесь 0 даёт false), то номер правильный | ||
+ | # $/${} is unnecessary on arithmetic variables. | ||
+ | if ! ((($terms) % 10)); then | ||
+ | echo " | ||
+ | else | ||
+ | echo " | ||
+ | fi | ||
+ | </ | ||
+ | https:// | ||
+ | |||
+ | ==== Шифр Атбаш ==== | ||
+ | При кодировании ('' | ||
+ | При декодировании ('' | ||
+ | <code bash> | ||
+ | declare -a az=( {a..z} ) | ||
+ | declare -a za=( {z..a} ) | ||
+ | |||
+ | str=" | ||
+ | str=$(echo " | ||
+ | |||
+ | declare -A array | ||
+ | for ((c=0; | ||
+ | array[${az[$c]}]=" | ||
+ | done | ||
+ | for n in {0..9}; do array[$n]=$n; | ||
+ | |||
+ | for ((c=0; | ||
+ | | ||
+ | done | ||
+ | |||
+ | case $1 in | ||
+ | encode) result=$(echo " | ||
+ | decode) echo " | ||
+ | esac | ||
+ | |||
+ | </ | ||
+ | |||
+ | ==== Строка наоборот ==== | ||
+ | <code bash> | ||
+ | input=" | ||
+ | |||
+ | for ((c=${# | ||
+ | str+=" | ||
+ | done | ||
+ | |||
+ | echo " | ||
+ | </ | ||
+ | |||
+ | ==== Проверка на високосный год ==== | ||
+ | Год должен делиться на 4, исключая те, что делятся на 100 (но если этот исключённый делится на 400, то включить). | ||
+ | <code bash> | ||
+ | # Аргумент должен присутствовать, | ||
+ | if [[ -z $* || -n ${*// | ||
+ | |||
+ | if (( $*%4==0 && ($*%100!=0 || $*%400==0) )); then | ||
+ | echo " | ||
+ | else | ||
+ | echo " | ||
+ | fi | ||
+ | </ | ||
+ | |||
+ | ==== Число резисторов ==== | ||
+ | <code bash> | ||
+ | declare -A array=( | ||
+ | [black]=0 | ||
+ | [brown]=1 | ||
+ | [red]=2 | ||
+ | [orange]=3 | ||
+ | [yellow]=4 | ||
+ | [green]=5 | ||
+ | [blue]=6 | ||
+ | [violet]=7 | ||
+ | [grey]=8 | ||
+ | [white]=9 | ||
+ | ) | ||
+ | |||
+ | # Непонятно, | ||
+ | # Arrays implicitly concatenate in [[ ]]. Use a loop (or explicit * instead of @). | ||
+ | if [[ ! ${!array[@]} =~ $1 || ! ${!array[@]} =~ $2 ]]; then | ||
+ | echo " | ||
+ | exit 1 | ||
+ | fi | ||
+ | # 1-е число не должно быть нулём | ||
+ | echo " | ||
+ | </ | ||
+ | https:// | ||
+ | |||
+ | Вариант 2 - резистора три, третий добавляет соответствующее кол-во нулей. От нулей зависит потом - кило- мега- гига- или просто омы. | ||
+ | <code bash> | ||
+ | shopt -s extglob | ||
+ | |||
+ | declare -A colors=( | ||
+ | [black]=0 | ||
+ | [brown]=1 | ||
+ | [red]=2 | ||
+ | [orange]=3 | ||
+ | [yellow]=4 | ||
+ | [green]=5 | ||
+ | [blue]=6 | ||
+ | [violet]=7 | ||
+ | [grey]=8 | ||
+ | [white]=9 | ||
+ | ) | ||
+ | |||
+ | zero() { | ||
+ | for ((c=1; | ||
+ | echo -n " | ||
+ | done | ||
+ | } | ||
+ | |||
+ | # Arrays implicitly concatenate in [[ ]]. Use a loop (or explicit * instead of @). | ||
+ | if [[ ! ${!colors[@]} =~ $1 || ! ${!colors[@]} =~ $2 || ! ${!colors[@]} =~ $3 ]]; then | ||
+ | echo "Wrong color" | ||
+ | exit 1 | ||
+ | fi | ||
+ | |||
+ | num=" | ||
+ | num=" | ||
+ | |||
+ | case " | ||
+ | *000000000) echo " | ||
+ | *000000) echo " | ||
+ | *000) echo " | ||
+ | *(0)) echo "0 ohms" ;; | ||
+ | *) echo "$num ohms" ;; | ||
+ | esac | ||
+ | </ | ||
+ | ==== Последовательность слов ==== | ||
+ | В соответствии с разрядами двоичного числа. Старший разряд - перевернуть массив. | ||
+ | <code bash> | ||
+ | bin=({0..1}{0..1}{0..1}{0..1}{0..1}) | ||
+ | n=" | ||
+ | |||
+ | if [[ ${n:4:1} -eq 1 ]]; then fw+=(" | ||
+ | if [[ ${n:3:1} -eq 1 ]]; then fw+=(" | ||
+ | if [[ ${n:2:1} -eq 1 ]]; then fw+=(" | ||
+ | if [[ ${n:1:1} -eq 1 ]]; then fw+=(" | ||
+ | if [[ ${n:0:1} -eq 1 ]]; then | ||
+ | for i in $(seq 1 ${#fw[@]}); do | ||
+ | rev+=(" | ||
+ | done | ||
+ | fi | ||
+ | |||
+ | # Разделитель IFS работает только с [*], с [@] - нет. | ||
+ | if [[ -n $rev ]]; then | ||
+ | IFS=, ; echo " | ||
+ | else | ||
+ | IFS=, ; echo " | ||
+ | fi | ||
+ | </ | ||
+ | |||
+ | ==== Дартс ==== | ||
+ | Радиус -1-1 - 10 очков, -5-5 - 5 очков, -10-10 - 1 очко. Допускаются дроби: -0.4, 5.5 и т. п.\\ | ||
+ | x< | ||
+ | https:// | ||
+ | <code bash> | ||
+ | if [[ $# -ne 2 || -n ${1// | ||
+ | echo " | ||
+ | exit 1 | ||
+ | fi | ||
+ | |||
+ | coord() { | ||
+ | echo "$1^2 + $2^2 <= $3" |bc | ||
+ | } | ||
+ | |||
+ | if [[ $(coord $1 $2 1) -eq 1 ]]; then | ||
+ | echo " | ||
+ | exit 0 | ||
+ | elif [[ $(coord $1 $2 25) -eq 1 ]]; then | ||
+ | echo " | ||
+ | exit 0 | ||
+ | elif [[ $(coord $1 $2 100) -eq 1 ]]; then | ||
+ | echo " | ||
+ | exit 0 | ||
+ | else | ||
+ | echo " | ||
+ | fi | ||
+ | </ | ||
+ | |||
+ | ==== Проверка правильности закрытия кавычек в строке ==== | ||
+ | Участвуют кавычки '' | ||
+ | <code bash> | ||
+ | declare -A ref=([\)]=' | ||
+ | str=" | ||
+ | |||
+ | for ((c=0; | ||
+ | cur=${str: | ||
+ | case $cur in | ||
+ | \{|\(|\[) a+=(" | ||
+ | # Arrays implicitly concatenate in [[ ]]. Use a loop (or explicit * instead of @). | ||
+ | *) if [[ -z ${a[@]} ]]; then | ||
+ | echo " | ||
+ | exit | ||
+ | else | ||
+ | # Quote the right-hand side of != in [[ ]] to prevent glob matching. | ||
+ | if [[ ${ref[$cur]} != ${a[-1]} ]]; then | ||
+ | echo " | ||
+ | exit | ||
+ | else | ||
+ | unset ' | ||
+ | fi | ||
+ | fi ;; | ||
+ | esac | ||
+ | done | ||
+ | |||
+ | # Arrays implicitly concatenate in [[ ]]. Use a loop (or explicit * instead of @). | ||
+ | if [[ -z ${a[@]} ]]; then | ||
+ | echo " | ||
+ | else | ||
+ | echo " | ||
+ | fi | ||
+ | </ | ||
+ | https:// | ||
+ | https:// | ||
+ | |||
+ | Гораздо более удобный вариант удаления последнего символа - '' | ||
+ | |||
+ | ==== Гвоздь и подкова ==== | ||
+ | Генератор пословицы из набора слов на входе. | ||
+ | <code bash> | ||
+ | a=(" | ||
+ | # Arrays implicitly concatenate in [[ ]]. Use a loop (or explicit * instead of @). | ||
+ | if [[ -z ${a[@]} ]]; then exit; fi | ||
+ | |||
+ | for ((c=0; | ||
+ | echo "For want of a ${a[$c]} the ${a[$c+1]} was lost." | ||
+ | done | ||
+ | |||
+ | echo "And all for the want of a ${a[0]}." | ||
+ | </ | ||
+ | For want of a nail the shoe was lost.\\ For want of a shoe the horse was lost.\\ For want of a horse the rider was lost.\\ For want of a rider the message was lost.\\ For want of a message the battle was lost.\\ For want of a battle the kingdom was lost.\\ And all for the want of a horseshoe nail.\\ | ||
+ | [[https:// |