== Усовершенсвование конструкции == === Усовершенсвование конструкции === ==== Усовершенсвование конструкции ==== ===== Усовершенсвование конструкции ===== ====== Усовершенсвование конструкции ====== **Изучаем новое в bash 4+ и вспоминаем старое.** - Усовершенсвование конструкции `case` пр помощи ;;& и ;&. ";&" - запустить действие приписанное к следующему шаблону ";;&" - продолжить проверку следующих шаблонов test_char () { case "$1" in [[:print:]] ) echo "$1 является печатным символом с пробелом";;& # ;;& продолжит проверку следующих шаблонов. [[:alnum:]] ) echo "$1 является буквой и цифрой";;& [[:alpha:]] ) echo "$1 является алфавитным символом.";;& [[:lower:]] ) echo "$1 является строчным алфавитным символом.";;& [[:digit:]] ) echo "$1 является десятичной цифрой";& # ;& запустит действие приписанное к следующему шаблону %%%@@@@@ ) echo "********************************";; esac } Передадим функции в качестве аргумента 8, получим 8 является печатным символом с пробелом 8 сожержит буквы и цифры 8 является десятичной цифрой ******************************** Передадим функции в качестве аргумента "n", получим n является печатным символом с пробелом n сожержит буквы и цифры n является алфавитными символом. n является строчным алфавитным символом. - Для управления асинхронным выполнением команд добавлено ключевое слово "coproc" Оператор coproc позволяет создавать со-процесс, который связан с командной оболочкой с помощью двух каналов: один для отправки данных в со-процесс, второй для получения из со-процесса. `coproc` запускает команду в фоне и выводит пайпы так, что снаружи с ними можно взаимодействовать. опционально сопроцессу можно дать имя `NAME`. Если задано `NAME`, следующая команда должная быть `compound command`. Если `NAME` не задано, команда может быть простой командой или тоже `compound`. — ${COPROC[0]} для записи; — ${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 а закрытие дескрипторов: $ exec {COPROC[1]}>&- $ cat <&"${COPROC[0]}" [1]+ Done coproc COPROC tr -u a b Если имя 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 ) - Добавлена новая встроенная команда "mapfile" (плюс добавлен синоним "readarray") для заполнения массива на основе строк указанного файла. Синтаксис следующий: mapfile [-n COUNT] [-O ORIGIN] [-s COUNT] [-t] [-u FD] [-C CALLBACK] [-c QUANTUM] [ARRAY] Пример mapfile Arr1 < test.txt echo "${Arr1[@]}" echo "${Arr1[@]}" #hello # world Только вот непоятно, почему добавлены пробелы, в исходном файле пробелов нет. `read` читает только первую строку файла в массив read -a Arr2 < test.txt echo "${Arr2[@]}" # hello - Изменено поведение встроенной функции read в момент истечения заданного таймаута, который можно задать через опцию "-t". Теперь при этом возвращается код ошибки больше 128 и сохраняются частично полученные до таймаута данные. Кроме того, таймаут теперь может принимать дробные значения. Дополнительно в read добавлена новая опция "-i", которая позволяет при использовании readline поместить введенный текст в буфер ответа (reply buffer) - В команде declare появилась поддержка преобразования регистра через указание опций -l (lowercase) и -u (uppercase) declare -l var1 var1="MixedCaseVARIABLE" echo "$var1" # mixedcasevariable Capitalize? declare -c var2 var2="originally lowercase" echo "$var2" #Originally lowercase - Раскрытие скобок 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 {40..60..-2} echo {X..d} # X Y Z [ ] ^ _ ` a b c d echo {000..10} # 000 001 002 003 004 005 006 007 008 009 010 - Реализована новая опция "globstar", при включении которой под маску `\*\*` подпадают все директории и файлы с использованием рекурсивного перебора #!/bin/bash shopt -s globstar # Необходимо включить globstar, противном случае `**` не работает. for filename in **; do echo "$filename" done - В переменной $BASHPID теперь сохраняется идентификатор (pid) текущего процесса - Реализована новая опция "autocd", при включении которой появляется возможность быстрого перехода в директории через ввод имени директории вместо команды (т.е. выполнение в интерактивной оболочке "dir" будет эквивалентно запуску "cd dir") - Если заданная команда не найдена, оболочка теперь пытается выполнить shell функцию с именем "command_not_found_handle", в которую в качестве аргументов передаются параметры не найденной команды - Если из-за недостатка ресурсов bash не удалось создать дочерний процесс, то перед выводом ошибки осуществляется еще несколько попыток - Добавлен новый оператор редиректа "&>>", который добавляет стандартный вывод и стандартный поток ошибок к заданному файлу - Для дополнения передаваемого следующему процессу стандартного вывода потоком ошибок, вместо конструкции `2>&1` теперь можно использовать синоним `|&` - Оболочка распознает новую команду для обрезание длинных путей PROMPT_DIRTRIM. В качестве значения указывается длина пути. После превышения заданной длины в приглашении ввода будет осуществлено обрезание длинных путей, заменяя конец на "..." - "printf -v" теперь позволяет назначить значение массиву индексов - Операторы "<" и ">" внутри условия "[[" теперь могут использоваться для сравнения строк с учетом текущей локали - В функцию read добавлена поддержка опции "-N число_символов", позволяющей считать из входного потока только заданное число символов num_chars=5 read -N $num_chars var < $0 # Читает первые 5 символов echo "$var" - Оператор включения файлов "source/." теперь удаляет нулевые символы из файла перед парсингом команд - Добавлена переменная $BASHOPTS для экспорта всех опций shell, установленных для дочерних процессов через shopt - Добавлена переменная $BASH_XTRACEFD, при установке в которую целого числа, bash начинает генерировать отладочный xtrace вывод в указанный файловый дескриптор - Bash теперь поддерживает \u и \U echo -e '\u2630' ☰ - Добавлена новая опция оболочки "lastpipe", позволяющая запустить последнюю команду из конвейера (pipeline) в контексте текущей оболочки #!/bin/bash line='' shopt -s lastpipe head -1 $0 | read line # Pipe the first line of the script to read. echo "\$line = "$line"" Получим $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 "" arr_mapfile < <(find -print0) echo "arr_mapfile contains ${#arr_mapfile[@]} files" # arr_mapfile contains 56380 files