在将变量作为命令运行时,如何阻止bash删除引号?

时间:2017-02-09 10:49:55

标签: bash

我有一个存储在变量中的命令,然后运行:

[root@cxpxwly01wel001 init.d]# cat test
#!/bin/bash
command="su - root -c 'java -Xms16m -the_rest_of_my_java_command'"
echo $command
$command
[root@cxpxwly01wel001 init.d]# ./test
su - root -c 'java -Xms16m -the_rest_of_my_java_command'
su: invalid option -- 'X'
Try `su --help' for more information.

如果单引号不存在,则会出现su错误:

[root@cxpxwly01wel001 init.d]# su - root -c java -Xms16m -the_rest_of_my_java_command
su: invalid option -- 'X'
Try `su --help' for more information.

使用单引号,命令按预期工作:

[root@cxpxwly01wel001 init.d]# su - root -c 'java -Xms16m -the_rest_of_my_java_command'
-bash: java: command not found

这告诉我,当将变量作为命令运行时,单引号不会被保留。我该如何保存它们?

注意:我正在编辑现有脚本(在java命令中插入su),所以我希望尽可能少地更改以使其靠近源。

让我在使用set -x

运行时添加输出
+ command='su - root -c '\''java -Xms16m -the_rest_of_my_java_command'\'''
+ echo su - root -c ''\''java' -Xms16m '-the_rest_of_my_java_command'\'''
su - root -c 'java -Xms16m -the_rest_of_my_java_command'
+ su - root -c ''\''java' -Xms16m '-the_rest_of_my_java_command'\'''
su: invalid option -- 'X'
Usage: su [options] [LOGIN]

Options:
  -c, --command COMMAND         pass COMMAND to the invoked shell
  -h, --help                    display this help message and exit
  -, -l, --login                make the shell a login shell
  -m, -p,
  --preserve-environment        do not reset environment variables, and
                                keep the same shell
  -s, --shell SHELL             use SHELL instead of the default in passwd

1 个答案:

答案 0 :(得分:1)

我用来避免“引用内引号”问题的技术是在数组中构建命令。例如,而不是:

command="su - root -c 'java -Xms16m -the_rest_of_my_java_command'"

我会用:

declare -a command=(su - root -c 'java -Xms16m -the_rest_of_my_java_command')

您仍然可以回显命令(使用数组扩展):

echo "${command[@]}"

或者运行它:

"${command[@]}"

数组扩展的双引号很重要:它们告诉shell扩展项而不进行任何单词拆分,因此包含空格的项将其标识保持为单个字符串。

通过这种方式,最后一个参数(在引号内)将保持为单个字符串,su命令不会将-Xms16m视为(无效)选项。

另外,[@]中的"${command[@]}"表示“数组中的所有元素”。然而,在"${command[1]}"这样的表达式中,[1]意味着“只有索引1处的元素”。