为什么需要使用 eval 来传递带引号的参数

为什么需要使用 eval 来传递带引号的参数

我有下面的例子。

#!/bin/bash
ARGUMENTS="-executors 1 -description \"The Host\" "

# call1
# error: parameter Host" is not allowed
java -jar swarm-client.jar $ARGUMENTS

# call2    
# works fine with eval
eval java -jar swarm-client.jar $ARGUMENTS

在 中$ARGUMENTS,我引用了一个论点。我不明白为什么通过转义引号对参数进行分组在call1.我不明白为什么有eval必要解决引用问题。

我想我不明白shell中命令评估的过程和顺序。你能给我解释一下吗?

答案1

你不传递带引号的参数对于命令,您可以传递参数。

当您输入:

cmd arg1 arg2

shell 以自己的语法解析该行,其中空格是单词分隔符,并使用cmd1,cmdarg1作为arg2参数进行调用。

笔记:cmd在其参数中不接收任何空格字符,空格只是 shell 语言语法中的运算符。

就像在 C 中一样,您func("foo", "bar")在运行时编写 ,func接收两个指针参数,它看不到任何(or,"或 空格字符。

shell 语法的一部分也是引用。"用于能够包含包含 shell 语法的其他部分的字符的单词。

当你这样做时:

cmd "arg 1" arg2

cmd接收cmd,arg 1arg2作为参数。它看不到任何"字符。它们"用于防止空格在 shell 语法中被视为单词分隔符。

现在,当你这样做时:

cmd $VAR

这与执行以下操作不同:

cmd the content of the variable

如果是这样,你就会遇到麻烦:

VAR='foo; reboot'
echo $VAR

例如。

在类似 Bourne 的 shell 中, 的内容$VAR不会作为单个参数逐字传递给cmd任何一个(不幸的是;它已在其他一些 shell 中得到修复,如、rc和在较小程度上)。相反,它会受到拆分和通配符 ( ) 的影响,并将生成的单词传递给.esfishzshsplit+globcmd

拆分是根据特殊$IFS变量中的字符进行的,默认为空格、制表符和换行符。

对于$ARGUMENTS包含 的内容,-executors 1 -description "The Host"它分为-executors1-description"TheHost"由于这些单词都不包含通配符,因此 glob 部分不适用,因此这些单词将被传递到cmd.

在这里,您可以使用split+glob运算符,并使用这些单词中未出现的字符作为分割部分的分隔符:

ARGUMENTS='-executors|1|-description|The Host'
IFS='|'
cmd $ARGUMENTS

或者更好的是,对于支持它们的 shell(例如bash),使用数组,您可以在其中包含一个包含所有这些参数的变量。

eval是评估shell代码。因此,另一个选择是包含ARGUMENTSshell 代码(shell 语法中的文本,而不是参数列表),并将其传递给eval解释。但请记住引用变量以避免 split+glob 运算符:

eval "cmd $ARGUMENTS"

答案2

当引号位于另一个字符串内时,bash 将其视为另一个字符。使用数组代替:

args=(-executors 1 -description "The Host")
java -jar swarm-client.jar "${args[@]}"

有关此问题的详细讨论,请参阅“我试图将命令放入变量中,但复杂的情况总是失败!”

另外,为变量使用小写或混合大小写的名称。系统使用所有大写字母作为变量名称,您不想意外覆盖其中之一。

怎么运行的

定义数组后args,单独的带引号的字符串将成为数组中单独的项。我们可以通过使用declare -p arrayname检查数组中的内容来看到这一点:

$ args=(-executors 1 -description "The Host")
$ declare -p args
declare -a args=([0]="-executors" [1]="1" [2]="-description" [3]="The Host")

正如我们所看到的,该字符串The Host是数组中的元素 3。

当bash扩展特殊形式时"${args[@]}",数组的每个元素都成为一个单独的元素。单词。这样,字符串The Host就保持为一单词即使它包含空格。

相关内容