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