我有一个脚本,除了执行位置参数之外没有任何用处。(我知道安全风险,并且该脚本没有任何用处,因为它是一个最小的工作示例。)
$ cat script
> #!/usr/bin/env bash
>
> eval "${*}"
$ cat "docu ment"
> Lorem ipsum dolor sit amet
我想做的是用./script cat "docu ment"
, 或调用脚本./script cat docu\ ment
,但引号或转义字符消失,脚本将尝试cat docu ment
,这是行不通的。在这种情况下,我将如何修复报价?
编辑:我真正想做的是多次调用命令,直到它返回成功的退出代码,或者它尝试了 n 次。我的脚本如下所示:
#!/usr/bin/env bash
# Try command several times, until it reports success (exit code 0)
# or I give up (tried n times)
tryMax=10
try=1
# Do until loop in bash
while
eval "${@}"
exitcode="${?}"
[[ "${exitcode}" -ne 0 && "${try}" -lt "${tryMax}" ]]
do (( try++ ))
done
if [[ "${exitcode}" -ne 0 ]]; then
echo -n "I tried hard, but did not manage to make this work. The exit code "
echo "of the last iteration of this command was: ${exitcode}."
exit "${exitcode}"
fi
你不需要
eval
这里。您可以使用"$@"
:"$@"
将扩展为脚本的所有参数作为单独的“单词” - 尊重防止分词的原始引用- 然后将第一个参数作为等待运行的命令(cat
),其余参数作为cat
(docu ment
)的参数.这不起作用的地方:
"$@"
扩展之后不会再次尝试。! cmd
。!
在开始处理命令时,在参数扩展之前也会处理。x \; y
或$'x\ny'
或x $'\n' y
,或与&&
或相同||
。所有这些都只是常规的论点。LD_LIBRARY_PATH=/x foo
. 您可以将它们放在脚本名称之前,但不能放在参数命令之前。>foo
,3<bar
则在其中。这些可能会或可能不会附加到脚本,因为脚本有自己的日志输出。eval
。( ... )
或命令组{ ... ; }
。这些将被视为称为(
and的命令{
,而不是语法结构。$(...)
。您可以使用它(或任何其他 shell 构造)来生成原始参数,但一旦脚本开始运行,它们都将是固定字符串。$RANDOM
或算术扩展$((i++))
。time
. 这是一个shell保留字,不是内置命令,所以也是在参数扩展前处理的。但是,否则,您可以成功地
eval
完全避免,并且可能应该这样做。即使忽略任何可能的安全问题,正确构建也是非常脆弱的。