Intereting Posts
Linux Mint 18 Cinnamon по умолчанию загружается в оболочку / командную строку / отключает графический интерфейс Где я могу найти «libgtk-3.so.0 () (64 бит)» для Amazon Linux? Обрезать линии между двумя разделителями Добавление XFCE в Linux Mint 15 Cinnamon? Как я могу выполнить сканирование на поверхности диска и исправить / перераспределить поврежденные сектора в Linux из командной строки? строка 7: [: ожидаемое выражение echo: integer Командная строка MySQL – привязывает клавишу <UP> к поиску обратной команды Как переименовать определенные каталоги, если у родителя есть определенное имя? Как узнать чувствительность Wi-Fi (RSSI) Что такое псевдотерминалы (pty / tty)? Включая .bash_profile через ssh OpenSUSE: найти все пакеты без репозитория Как подавить сообщения об ошибках из cp? Что происходит со старым двоичным кодом, когда новый компилируется из источника? Запуск crontab только при условии

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

У меня есть этот код в инструменте, который я сейчас создаю:

while [ $# -gt 0 ]; do case "$1" in --var1=*) var1="${1#*=}" ;; --var2=*) var1="${1#*=}" ;; --var3=*) var1="${1#*=}" ;; *) printf "***************************\n * Error: Invalid argument.*\n ***************************\n" esac shift done 

У меня есть много вариантов добавления, но пять из моих параметров должны быть сохранены как массивы. Поэтому, если я вызову инструмент, скажем, из оболочки, используя что-то вроде этого:
./tool --var1="2" --var1="3" --var1="4" --var1="5" --var2="6" --var3="7"

Как сохранить значение var1 как массив? Это возможно? И если да, то каков наилучший способ справиться с этими массивами с точки зрения эффективности, если у меня их слишком много ?.

Если в Linux (с утилитами util-linux включая getopt , или один из busybox ), вы можете сделать:

 declare -A opt_spec var1=() var2=() var4=false unset var3 opt_spec=( [opt1:]='var1()' # opt with argument, array variable [opt2:]='var2()' # ditto [opt3:]='var3' # opt with argument, scalar variable [opt4]='var4' # boolean opt without argument ) parsed_opts=$( IFS=, getopt -o + -l "${!opt_spec[*]}" -- "$@" ) || exit eval "set -- $parsed_opts" while [ "$#" -gt 0 ]; do o=$1; shift case $o in (--) break;; (--*) o=${o#--} if ((${opt_spec[$o]+1})); then # opt without argument eval "${opt_spec[$o]}=true" else o=$o: case "${opt_spec[$o]}" in (*'()') eval "${opt_spec[$o]%??}+=(\"\$1\")";; (*) eval "${opt_spec[$o]}=\$1" esac shift fi esac done echo "var1: ${var1[@]}" 

Таким образом, вы можете назвать свой сценарий следующим:

 my-script --opt1=foo --opt2 bar --opt4 -- whatever 

И getopt будет выполнять тяжелую работу по разбору, обработке и сокращению для вас.

В качестве альтернативы вы можете полагаться на тип переменной вместо указания ее в $opt_spec ассоциативного массива $opt_spec :

 declare -A opt_spec var1=() var2=() var4=false unset var3 opt_spec=( [opt1:]=var1 # opt with argument [opt2:]=var2 # ditto [opt3:]=var3 # ditto [opt4]=var4 # boolean opt without argument ) parsed_opts=$( IFS=, getopt -o + -l "${!opt_spec[*]}" -- "$@" ) || exit eval "set -- $parsed_opts" while [ "$#" -gt 0 ]; do o=$1; shift case $o in (--) break;; (--*) o=${o#--} if ((${opt_spec[$o]+1})); then # opt without argument eval "${opt_spec[$o]}=true" else o=$o: case $(declare -p "${opt_spec[$o]}" 2> /dev/null) in ("declare -a"*) eval "${opt_spec[$o]}+=(\"\$1\")";; (*) eval "${opt_spec[$o]}=\$1" esac shift fi esac done echo "var1: ${var1[@]}" 

Вы можете добавить короткие варианты, например:

 declare -A long_opt_spec short_opt_spec var1=() var2=() var4=false unset var3 long_opt_spec=( [opt1:]=var1 # opt with argument [opt2:]=var2 # ditto [opt3:]=var3 # ditto [opt4]=var4 # boolean opt without argument ) short_opt_spec=( [a:]=var1 [b:]=var2 [c]=var3 [d]=var4 ) parsed_opts=$( IFS=; short_opts="${!short_opt_spec[*]}" IFS=, getopt -o "+$short_opts" -l "${!long_opt_spec[*]}" -- "$@" ) || exit eval "set -- $parsed_opts" while [ "$#" -gt 0 ]; do o=$1; shift case $o in (--) break;; (--*) o=${o#--} if ((${long_opt_spec[$o]+1})); then # opt without argument eval "${long_opt_spec[$o]}=true" else o=$o: case $(declare -p "${long_opt_spec[$o]}" 2> /dev/null) in ("declare -a"*) eval "${long_opt_spec[$o]}+=(\"\$1\")";; (*) eval "${long_opt_spec[$o]}=\$1" esac shift fi;; (-*) o=${o#-} if ((${short_opt_spec[$o]+1})); then # opt without argument eval "${short_opt_spec[$o]}=true" else o=$o: case $(declare -p "${short_opt_spec[$o]}" 2> /dev/null) in ("declare -a"*) eval "${short_opt_spec[$o]}+=(\"\$1\")";; (*) eval "${short_opt_spec[$o]}=\$1" esac shift fi esac done echo "var1: ${var1[@]}" 

Я бы предложил вам взглянуть на мой General Shell Script GitHub: utility_functions.sh . Там вы увидите функцию getArgs . Он предназначен для сопоставления опций и значений.

Я вставляю здесь только функцию, но это зависит от еще нескольких функций внутри этого скрипта

 ########################## # # Function name: getArgs # # Description: # This function provides the getopts functionality # while allowing the use of long operations and list of parameters. # in the case of a list of arguments for only one option, this list # will be returned as a single-space-separated list in one single string. # # Pre-reqs: # None # # Output: # GA_OPTION variable will hold the current option # GA_VALUE variable will hold the value (or list of values) associated # with the current option # # Usage: # You have to source the function in order to be able to access the GA_OPTIONS # and GA_VALUES variables # . getArgs $* # #################### function getArgs { # Variables to return the values out of the function typeset -a GA_OPTIONS typeset -a GA_VALUES # Checking for number of arguments if [[ -z $1 ]] then msgPrint -warning "No arguments found" msgPrint -info "Please call this function as follows: . getArgs \$*" exit 0 fi # Grab the dash dash=$(echo $1 | grep "-") # Looking for short (-) or long (--) options isOption=$(expr index "$dash" "-") # Initialize the counter counter=0 # Loop while there are arguments left while [[ $# -gt 0 ]] do if [[ $dash && $isOption -eq 1 ]] then (( counter+=1 )) GA_OPTIONS[$counter]=$1 shift else if [[ -z ${GA_VALUES[$counter]} ]] then GA_VALUES[$counter]=$1 else GA_VALUES[$counter]="${GA_VALUES[$counter]} $1" fi shift fi dash=$(echo $1 | grep "-") isOption=$(expr index "$dash" "-") done # Make the variables available to the main algorithm export GA_OPTIONS export GA_VALUES msgPrint -debug "Please check the GA_OPTIONS and GA_VALUES arrays for options and arguments" # Exit with success return 0 } 

Как вы видите, эта функция будет экспортировать GA_OPTIONS и GA_VALUES. Только условие для этого состоит в том, что после опции значения должны быть списком, разделенным пробелом.

Вы могли бы назвать скрипт как ./tool ​​–var1 2 3 4 5 –var2 = "6" –var3 = "7"

Или просто используйте аналогичную логику, чтобы учесть ваши предпочтения.

Надеюсь это поможет.