Bash - 如何避免命令“eval set --"评估变量 [英] Bash - how to avoid command "eval set --" evaluating variables

查看:108
本文介绍了Bash - 如何避免命令“eval set --"评估变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我只是写了一个小 bash 脚本来管理多个并行 ssh 命令.为了解析参数,我使用了这段代码:

I just write a little bash script for managing multiple parallels ssh commands. In order to parse arguments I use this piece of code :

#!/bin/bash

# replace long arguments
for arg in "$@"; do
    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; do
    echo "optarg : $OPTARG"
    case $OPTION in
    h)  usage; exit 0;;
    s)  servers_array+=("$OPTARG");;
    c)  cmd="$OPTARG";;
    esac
done

所以我可以使用 -s、--host 或 -hS 来获得相同的结果.除了一件事外,一切正常.

So I can use for instance -s, --host or -hS for the same result. Everything works fine except one thing.

如果我在参数中放入一个变量,它将被评估.

If I put a variable in argument it will be evaluated.

./test.sh -s SERVER -c 'echo $HOSTNAME'

  1. cmd 应该分配给 echo $HOSTNAME 但由于 eval set cmd 实际上分配给 echo server1(变量的值)

  1. cmd should be assigned to echo $HOSTNAME but because of the eval set cmd is in fact assigned to echo server1 (the value of the variable)

如果我注释行 eval set -- $args 我不能使用长选项 (--cmd) 但 cmd 被分配给 echo$HOSTNAME 符合预期

If I comment the line eval set -- $args I cannot use long options (--cmd) but cmd is assigned to echo $HOSTNAME as expected

是否有任何解决方案可以避免使用 eval set/getopts 来评估变量?所以要具有与 2. 相同的行为,但有很长的选项可用.

Is there any solution to avoid eval set / getopts to evaluate variables ? So to to have the same behavior as 2. but with long options available.

带有评估集

./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

没有 eval set(行 eval set -- $args 注释)

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

推荐答案

如您所见,eval 是邪恶的 -- 这里没有必要使用它.

As you note, eval is evil -- and there's no need to use it here.

#!/bin/bash

# make args an array, not a string
args=( )

# replace long arguments
for arg; do
    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; do
    : "$OPTION" "$OPTARG"
    echo "optarg : $OPTARG"
    case $OPTION in
    h)  usage; exit 0;;
    s)  servers_array+=("$OPTARG");;
    c)  cmd="$OPTARG";;
    esac
done

也就是说:在构建命令行时,将单个项追加到数组中;然后,您可以扩展该数组,引用,而不会因字符串拆分、全局扩展等的影响而冒评估或不良行为的风险.

That is to say: When building up a command line, append individual items to an array; you can then expand that array, quoted, without risking either evaluation or undesired behavior via effects of string-splitting, glob expansion, etc.

这篇关于Bash - 如何避免命令“eval set --"评估变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆