Что Нового Появилось В Bash 4.0
Различия
Здесь показаны различия между двумя версиями данной страницы.
Следующая версия | Предыдущая версия | ||
черновики:что_нового_появилось_в_bash_4.0 [08.05.2017 18:15] zimo создано |
черновики:что_нового_появилось_в_bash_4.0 [20.05.2019 15:18] (текущий) |
||
---|---|---|---|
Строка 1: | Строка 1: | ||
- | Изучаем новое в bash 4+ и вспоминаем старое. | + | |
+ | == Усовершенсвование конструкции == | ||
+ | |||
+ | === Усовершенсвование конструкции === | ||
+ | |||
+ | ==== Усовершенсвование конструкции ==== | ||
+ | |||
+ | ===== Усовершенсвование конструкции ===== | ||
+ | |||
+ | ====== Усовершенсвование конструкции ====== | ||
+ | |||
+ | |||
+ | **Изучаем новое в bash 4+ и вспоминаем старое.** | ||
- Усовершенсвование конструкции `case` пр помощи ;;& и ;&. | - Усовершенсвование конструкции `case` пр помощи ;;& и ;&. | ||
- | ";&" - запустить действие приписанное к следующему шаблону\\ | + | ";&" - запустить действие приписанное к следующему шаблону |
- | ";;&" - продолжить проверку следующих шаблонов | + | ";;&" - продолжить проверку следующих шаблонов |
- | ```\\ | + | <code bash> |
- | test_char ()\\ | + | test_char () |
- | {\\ | + | { |
- | case "$1" in\\ | + | case "$1" in |
- | [[:print:]] ) echo "$1 является печатным символом с пробелом";;&\\ | + | [[:print:]] ) echo "$1 является печатным символом с пробелом";;& |
- | # ;;& продолжит проверку следующих шаблонов.\\ | + | # ;;& продолжит проверку следующих шаблонов. |
- | [[:alnum:]] ) echo "$1 является буквой и цифрой";;&\\ | + | [[:alnum:]] ) echo "$1 является буквой и цифрой";;& |
- | [[:alpha:]] ) echo "$1 является алфавитным символом.";;&\\ | + | [[:alpha:]] ) echo "$1 является алфавитным символом.";;& |
- | [[:lower:]] ) echo "$1 является строчным алфавитным символом.";;&\\ | + | [[:lower:]] ) echo "$1 является строчным алфавитным символом.";;& |
- | [[:digit:]] ) echo "$1 является десятичной цифрой";& \\ | + | [[:digit:]] ) echo "$1 является десятичной цифрой";& |
- | # ;& запустит действие приписанное к следующему шаблону \\ | + | # ;& запустит действие приписанное к следующему шаблону |
- | %%%@@@@@ ) echo "********************************";;\\ | + | %%%@@@@@ ) echo "********************************";; |
- | esac\\ | + | esac |
- | }\\ | + | } |
- | ``` | + | </code> |
Передадим функции в качестве аргумента 8, получим | Передадим функции в качестве аргумента 8, получим | ||
- | ```\\ | + | <code bash> |
- | 8 является печатным символом с пробелом\\ | + | 8 является печатным символом с пробелом |
- | 8 сожержит буквы и цифры\\ | + | 8 сожержит буквы и цифры |
- | 8 является десятичной цифрой\\ | + | 8 является десятичной цифрой |
- | ********************************\\ | + | ******************************** |
- | ``` | + | </code> |
Передадим функции в качестве аргумента "n", получим | Передадим функции в качестве аргумента "n", получим | ||
- | ```\\ | + | |
- | n является печатным символом с пробелом\\ | + | <code bash> |
- | n сожержит буквы и цифры\\ | + | n является печатным символом с пробелом |
- | n является алфавитными символом.\\ | + | n сожержит буквы и цифры |
- | n является строчным алфавитным символом.\\ | + | n является алфавитными символом. |
- | ```\\ | + | n является строчным алфавитным символом. |
+ | </code> | ||
- Для управления асинхронным выполнением команд добавлено ключевое слово "coproc" | - Для управления асинхронным выполнением команд добавлено ключевое слово "coproc" | ||
Оператор coproc позволяет создавать со-процесс, который связан с командной оболочкой с помощью двух каналов: один для отправки данных в со-процесс, второй для получения из со-процесса. | Оператор coproc позволяет создавать со-процесс, который связан с командной оболочкой с помощью двух каналов: один для отправки данных в со-процесс, второй для получения из со-процесса. | ||
- | `coproc` запускает команду в фоне и выводит пайпы так, что снаружи с ними можно взаимодействовать. опционально сопроцессу можно дать имя `NAME`.\\ | + | `coproc` запускает команду в фоне и выводит пайпы так, что снаружи с ними можно взаимодействовать. опционально сопроцессу можно дать имя `NAME`. |
- | Если задано `NAME`, следующая команда должная быть `compound command`. Если `NAME` не задано, команда может быть простой командой или тоже `compound`. | + | Если задано `NAME`, следующая команда должная быть `compound command`. Если `NAME` не задано, команда может быть простой командой или тоже `compound`. |
- | — ${COPROC[0]} для записи;\\ | + | — ${COPROC[0]} для записи; |
— ${COPROC[1]} для чтения. | — ${COPROC[1]} для чтения. | ||
Соответственно, процедура записи/чтения будет выглядеть примерно так: | Соответственно, процедура записи/чтения будет выглядеть примерно так: | ||
- | ```\\ | + | |
- | $ coproc tr -u a b\\ | + | <code bash> |
- | [1] 30131\\ | + | $ coproc tr -u a b |
- | $ echo abrakadabra1 >&${COPROC[1]}\\ | + | [1] 30131 |
- | $ echo abrakadabra2 >&${COPROC[1]}\\ | + | $ echo abrakadabra1 >&${COPROC[1]} |
- | $ echo abrakadabra3 >&${COPROC[1]}\\ | + | $ echo abrakadabra2 >&${COPROC[1]} |
- | $ while read -u ${COPROC[0]}; do printf "%s\n" "$REPLY"; done\\ | + | $ echo abrakadabra3 >&${COPROC[1]} |
- | bbrbkbdbbrb1\\ | + | $ while read -u ${COPROC[0]}; do printf "%s\n" "$REPLY"; done |
- | bbrbkbdbbrb2\\ | + | bbrbkbdbbrb1 |
- | bbrbkbdbbrb3\\ | + | bbrbkbdbbrb2 |
- | ``` | + | bbrbkbdbbrb3 |
+ | </code> | ||
а закрытие дескрипторов: | а закрытие дескрипторов: | ||
- | ```\\ | + | <code bash> |
- | $ exec {COPROC[1]}>&-\\ | + | |
- | $ cat <&"${COPROC[0]}"\\ | + | $ exec {COPROC[1]}>&- |
- | [1]+ Done coproc COPROC tr -u a b\\ | + | $ cat <&"${COPROC[0]}" |
- | ``` | + | [1]+ Done coproc COPROC tr -u a b |
+ | |||
+ | </code> | ||
Если имя COPROC по каким-то причинам не устраивает можно указать свое: | Если имя COPROC по каким-то причинам не устраивает можно указать свое: | ||
- | ```\\ | + | <code bash> |
- | $ coproc MYNAME (tr -u a b)\\ | + | $ coproc MYNAME (tr -u a b) |
- | [1] 30528\\ | + | [1] 30528 |
- | $ echo abrakadabra1 >&${MYNAME[1]}\\ | + | $ echo abrakadabra1 >&${MYNAME[1]} |
- | $ read -u ${MYNAME[0]} ; echo $REPLY\\ | + | $ read -u ${MYNAME[0]} ; echo $REPLY |
- | bbrbkbdbbrb1\\ | + | bbrbkbdbbrb1 |
- | $ exec {MYNAME[1]}>&- ; cat <&"${MYNAME[0]}"\\ | + | $ exec {MYNAME[1]}>&- ; cat <&"${MYNAME[0]}" |
- | [1]+ Done coproc MYNAME ( tr -u a b )\\ | + | [1]+ Done coproc MYNAME ( tr -u a b ) |
- | ``` | + | </code> |
- Добавлена новая встроенная команда "mapfile" (плюс добавлен синоним "readarray") для заполнения массива на основе строк указанного файла. | - Добавлена новая встроенная команда "mapfile" (плюс добавлен синоним "readarray") для заполнения массива на основе строк указанного файла. | ||
Строка 87: | Строка 106: | ||
Синтаксис следующий: | Синтаксис следующий: | ||
- | ```\\ | + | <code bash> |
- | mapfile [-n COUNT] [-O ORIGIN] [-s COUNT] [-t] [-u FD] [-C CALLBACK] [-c QUANTUM] [ARRAY]\\ | + | mapfile [-n COUNT] [-O ORIGIN] [-s COUNT] [-t] [-u FD] [-C CALLBACK] [-c QUANTUM] [ARRAY] |
- | ``` | + | </code> |
Пример | Пример | ||
- | ```\\ | + | <code bash> |
- | mapfile Arr1 < test.txt\\ | + | mapfile Arr1 < test.txt |
- | echo "${Arr1[@]}"\\ | + | echo "${Arr1[@]}" |
- | echo "${Arr1[@]}"\\ | + | echo "${Arr1[@]}" |
- | #hello\\ | + | #hello |
- | # world\\ | + | # world |
- | ``` | + | </code> |
Только вот непоятно, почему добавлены пробелы, в исходном файле пробелов нет. | Только вот непоятно, почему добавлены пробелы, в исходном файле пробелов нет. | ||
Строка 105: | Строка 124: | ||
`read` читает только первую строку файла в массив | `read` читает только первую строку файла в массив | ||
- | ```\\ | + | <code bash> |
- | read -a Arr2 < test.txt\\ | + | read -a Arr2 < test.txt |
- | echo "${Arr2[@]}"\\ | + | echo "${Arr2[@]}" |
- | # hello\\ | + | # hello |
- | ``` | + | </code> |
- Изменено поведение встроенной функции read в момент истечения заданного таймаута, который можно задать через опцию "-t". Теперь при этом возвращается код ошибки больше 128 и сохраняются частично полученные до таймаута данные. Кроме того, таймаут теперь может принимать дробные значения. Дополнительно в read добавлена новая опция "-i", которая позволяет при использовании readline поместить введенный текст в буфер ответа (reply buffer) | - Изменено поведение встроенной функции read в момент истечения заданного таймаута, который можно задать через опцию "-t". Теперь при этом возвращается код ошибки больше 128 и сохраняются частично полученные до таймаута данные. Кроме того, таймаут теперь может принимать дробные значения. Дополнительно в read добавлена новая опция "-i", которая позволяет при использовании readline поместить введенный текст в буфер ответа (reply buffer) | ||
Строка 115: | Строка 134: | ||
- В команде declare появилась поддержка преобразования регистра через указание опций -l (lowercase) и -u (uppercase) | - В команде declare появилась поддержка преобразования регистра через указание опций -l (lowercase) и -u (uppercase) | ||
- | ```\\ | + | <code bash> |
- | declare -l var1\\ | + | declare -l var1 |
- | var1="MixedCaseVARIABLE"\\ | + | var1="MixedCaseVARIABLE" |
- | echo "$var1"\\ | + | echo "$var1" |
# mixedcasevariable | # mixedcasevariable | ||
+ | </code> | ||
- | ```\\ | ||
Capitalize? | Capitalize? | ||
- | ```\\ | + | <code bash> |
- | declare -c var2\\ | + | declare -c var2 |
- | var2="originally lowercase"\\ | + | var2="originally lowercase" |
- | echo "$var2"\\ | + | echo "$var2" |
- | #Originally lowercase\\ | + | #Originally lowercase |
- | ``` | + | |
+ | </code> | ||
- Раскрытие скобок | - Раскрытие скобок | ||
- | ```\\ | + | <code bash> |
- | echo {40..60..2}\\ | + | echo {40..60..2} |
# 40 42 44 46 48 50 52 54 56 58 60 | # 40 42 44 46 48 50 52 54 56 58 60 | ||
- | # Декремент\\ | + | # Декремент |
- | echo {60..40..2}\\ | + | echo {60..40..2} |
# 60 58 56 54 52 50 48 46 44 42 40 | # 60 58 56 54 52 50 48 46 44 42 40 | ||
- | # Так не работает\\ | + | # Так не работает |
echo {40..60..-2} | echo {40..60..-2} | ||
- | echo {X..d}\\ | + | echo {X..d} |
# X Y Z [ ] ^ _ ` a b c d | # X Y Z [ ] ^ _ ` a b c d | ||
- | echo {000..10}\\ | + | echo {000..10} |
- | # 000 001 002 003 004 005 006 007 008 009 010\\ | + | # 000 001 002 003 004 005 006 007 008 009 010 |
- | ``` | + | |
- | - Реализована новая опция "globstar", при включении которой под маску `**` подпадают все директории и файлы с использованием рекурсивного перебора | + | </code> |
- | ```\\ | ||
- | #!/bin/bash | ||
- | shopt -s globstar # Необходимо включить globstar, противном случае ** не работает. | + | - Реализована новая опция "globstar", при включении которой под маску `\*\*` подпадают все директории и файлы с использованием рекурсивного перебора |
+ | |||
+ | <code bash> | ||
+ | #!/bin/bash | ||
- | shopt -s globstar | + | shopt -s globstar # Необходимо включить globstar, противном случае `**` не работает. |
- | for filename in **; do\\ | + | for filename in **; do |
- | echo "$filename"\\ | + | echo "$filename" |
- | done\\ | + | done |
- | ``` | + | </code> |
- В переменной $BASHPID теперь сохраняется идентификатор (pid) текущего процесса | - В переменной $BASHPID теперь сохраняется идентификатор (pid) текущего процесса | ||
Строка 185: | Строка 205: | ||
- В функцию read добавлена поддержка опции "-N число_символов", позволяющей считать из входного потока только заданное число символов | - В функцию read добавлена поддержка опции "-N число_символов", позволяющей считать из входного потока только заданное число символов | ||
- | ```\\ | + | <code bash> |
- | num_chars=5\\ | + | num_chars=5 |
- | read -N $num_chars var < $0 # Читает первые 5 символов\\ | + | read -N $num_chars var < $0 # Читает первые 5 символов |
- | echo "$var"\\ | + | echo "$var" |
- | ``` | + | </code> |
- Оператор включения файлов "source/." теперь удаляет нулевые символы из файла перед парсингом команд | - Оператор включения файлов "source/." теперь удаляет нулевые символы из файла перед парсингом команд | ||
Строка 199: | Строка 219: | ||
- Bash теперь поддерживает \u и \U | - Bash теперь поддерживает \u и \U | ||
- | ```\\ | + | <code bash> |
- | echo -e '\u2630'\\ | + | echo -e '\u2630' |
- | ☰\\ | + | ☰ |
- | ``` | + | </code> |
- Добавлена новая опция оболочки "lastpipe", позволяющая запустить последнюю команду из конвейера (pipeline) в контексте текущей оболочки | - Добавлена новая опция оболочки "lastpipe", позволяющая запустить последнюю команду из конвейера (pipeline) в контексте текущей оболочки | ||
- | ```\\ | + | <code bash> |
#!/bin/bash | #!/bin/bash | ||
- | line='' | + | line='' |
- | shopt -s lastpipe \\ | + | shopt -s lastpipe |
- | head -1 $0 | read line # Pipe the first line of the script to read.\\ | + | head -1 $0 | read line # Pipe the first line of the script to read. |
- | echo "\$line = "$line""\\ | + | echo "\$line = "$line"" |
- | ``` | + | |
+ | </code> | ||
Получим | Получим | ||
- | ```\\ | + | <code bash> |
- | $line = #!/bin/bash\\ | + | |
- | ``` | + | $line = #!/bin/bash |
+ | |||
+ | </code> | ||
- Отрицательные индексы массива | - Отрицательные индексы массива | ||
- | ```\\ | + | <code bash> |
- | array=( zero one two three four five )\\ | + | |
- | # 0 1 2 3 4 5\\ | + | array=( zero one two three four five ) |
- | # -6 -5 -4 -3 -2 -1\\ | + | # 0 1 2 3 4 5 |
- | echo ${array[-1]} # five\\ | + | # -6 -5 -4 -3 -2 -1 |
- | echo ${array[-2]} # four\\ | + | echo ${array[-1]} # five |
- | ``` | + | echo ${array[-2]} # four |
+ | |||
+ | </code> | ||
- Отрицательный размер, указанный в блоке ${var:offset:length} теперь не приводит к ошибке и воспринимается как обратное смещение от конца переменной | - Отрицательный размер, указанный в блоке ${var:offset:length} теперь не приводит к ошибке и воспринимается как обратное смещение от конца переменной | ||
- | ```\\ | + | |
+ | <code bash> | ||
stringZ=abcABC123ABCabc | stringZ=abcABC123ABCabc | ||
- | echo ${stringZ} # abcABC123ABCabc\\ | + | echo ${stringZ} # abcABC123ABCabc |
- | # Position within string: 0123456789.....\\ | + | # Position within string: 0123456789..... |
- | echo ${stringZ:2:3} # cAB\\ | + | echo ${stringZ:2:3} # cAB |
- | # Count 2 chars forward from string beginning, and extract 3 chars.\\ | + | # Count 2 chars forward from string beginning, and extract 3 chars. |
- | # ${string:position:length}\\ | + | # ${string:position:length} |
- | # abcABC123ABCabc\\ | + | # abcABC123ABCabc |
- | # Position within string: 0123....6543210\\ | + | # Position within string: 0123....6543210 |
- | echo ${stringZ:3:-6}\\ | + | echo ${stringZ:3:-6} |
- | ``` | + | |
+ | </code> | ||
- Для команд declare/typeset добавлена новая опция "-g", при указании которой переменные имеют глобальную область видимости, т.е. видны даже в отдельных функциях | - Для команд declare/typeset добавлена новая опция "-g", при указании которой переменные имеют глобальную область видимости, т.е. видны даже в отдельных функциях | ||
Строка 255: | Строка 283: | ||
- Во встроенной команде printf добавлена поддержка спецификатора "%(fmt)T", позволяющего указать формат вывода времени в стиле strftime | - Во встроенной команде printf добавлена поддержка спецификатора "%(fmt)T", позволяющего указать формат вывода времени в стиле strftime | ||
- | #### 4.3 | + | **4.3** |
- | - Поддержка назначения и использования элементов массивов с отрицательными значениями индекса | + | - Поддержка назначения и использования элементов массивов с отрицательными значениями индекса |
- | ```\\ | ||
- | a[-1]=2\\ | ||
- | echo ${a[-1]} # 2\\ | ||
- | ``` | ||
- | При этом, отрицательное значение задаёт обратный отчёт с последнего элемента массива (a[-1] - последний элемент, a[-2] - предпоследний и т.п.). | + | <code bash> |
+ | a[-1]=2 | ||
+ | echo ${a[-1]} # 2 | ||
+ | |||
+ | </code> | ||
+ | |||
+ | При этом, отрицательное значение задаёт обратный отчёт с последнего элемента массива (a[-1] - последний элемент, a[-2] - предпоследний и т.п.). | ||
- В командах return и exit добавлена возможность указания отрицательных кодов завершения работы | - В командах return и exit добавлена возможность указания отрицательных кодов завершения работы | ||
- | - При указании %(...)T в printf без явного указания аргументов формата теперь выводится текущее время. | + | - При указании %(...)T в printf без явного указания аргументов формата теперь выводится текущее время. |
- | ```\\ | ||
- | printf '%(%Y%m%d)T\n'\\ | ||
- | # 20170217\\ | ||
- | ``` | ||
- | #### 4.4 | + | <code bash> |
+ | printf '%(%Y%m%d)T\n' | ||
+ | # 20170217 | ||
+ | </code> | ||
+ | |||
+ | **4.4** | ||
- Во встроенной команде mapfile появилась возможность определения произвольного символа-разделителя записей (опция "-d") | - Во встроенной команде mapfile появилась возможность определения произвольного символа-разделителя записей (опция "-d") | ||
- | ```\\ | + | |
- | mapfile -d "" arr_mapfile < <(find -print0)\\ | + | <code bash> |
- | echo "arr_mapfile contains ${#arr_mapfile[@]} files"\\ | + | mapfile -d "" arr_mapfile < <(find -print0) |
- | # arr_mapfile contains 56380 files\\ | + | echo "arr_mapfile contains ${#arr_mapfile[@]} files" |
- | ``` | + | # arr_mapfile contains 56380 files |
+ | |||
+ | </code> | ||