Bash - how to avoid command "eval set --" evaluating variables -
i write little bash script managing multiple parallels ssh commands. in order parse arguments use piece of code :
#!/bin/bash # replace long arguments arg in "$@"; case "$arg" in --help) args="${args}-h ";; --host|-hs) args="${args}-s ";; --cmd) args="${args}-c ";; *) [[ "${arg:0:1}" == "-" ]] && delim='' || delim="\"" args="${args}${delim}${arg}${delim} ";; esac done echo "args before eval : $args" eval set -- $args echo "args after eval : $args" while getopts "hs:c:" option; echo "optarg : $optarg" case $option in h) usage; exit 0;; s) servers_array+=("$optarg");; c) cmd="$optarg";; esac done
so can use instance -s, --host or -hs same result. works fine except 1 thing.
if put variable in argument evaluated.
explanations
./test.sh -s server -c 'echo $hostname'
cmd
should assignedecho $hostname
because ofeval set
cmd in fact assignedecho server1
(the value of variable)if comment line
eval set -- $args
cannot use long options (--cmd)cmd
assignedecho $hostname
expected
is there solution avoid eval set / getopts evaluate variables ? to have same behavior 2. long options available.
examples
with eval set
./test.sh -s server -c 'echo $hostname' args before eval : -s "server" -c "echo $hostname" args after eval : -s "server" -c "echo $hostname" optarg : server optarg : echo server1
without eval set (line eval set -- $args
commented)
./test.sh -s server -c 'echo $hostname' args before eval : -s "server" -c "echo $hostname" args after eval : -s "server" -c "echo $hostname" optarg : server optarg : echo $hostname
as note, eval
evil -- , there's no need use here.
#!/bin/bash # make args array, not string args=( ) # replace long arguments arg; case "$arg" in --help) args+=( -h ) ;; --host|-hs) args+=( -s ) ;; --cmd) args+=( -c ) ;; *) args+=( "$arg" ) ;; esac done printf 'args before update : '; printf '%q ' "$@"; echo set -- "${args[@]}" printf 'args after update : '; printf '%q ' "$@"; echo while getopts "hs:c:" option; : "$option" "$optarg" echo "optarg : $optarg" case $option in h) usage; exit 0;; s) servers_array+=("$optarg");; c) cmd="$optarg";; esac done
that say: when building command line, amend individual items array; can expand array, quoted, without risking either evaluation or undesired behavior via effects of string-splitting, glob expansion, etc.
Comments
Post a Comment