在bash中转义&符号

3

I have the following code:

ANSIBLE_WORK_DIR=${ANSIBLE_WORK_DIR:-$(pwd)/ansible}

ansible_work_dir() {
  echo "${ANSIBLE_WORK_DIR}"
}

ansible_run() {
  local cmd
  ansible_dir=$(ansible_work_dir)

  cmd="cd $ansible_dir && ansible-playbook --extra-vars env=${ENV}"
  $cmd "${@}"
}

ansible_run playbooks/secrets/write.yml

我的问题是,我得到的结果如下所示:
cd /home/ubuntu/ansible '&&' ansible-playbook --extra-vars env=test playbooks/secrets/write.yml

我发现双“&”符在某些情况下会被转义,请问该怎么解决这个问题?

4
请查看Bash FAQ#50 - PesaThe
2
@randomir,...从狭义上讲,这样做可以实现OP想要的功能,但也存在一些OP不想要的风险——特别是使用"$@"作为单独参数传递时,eval将有效地拆分它类似于$*,然后重新解析(从头开始,因此将字符串中的$()视为运行命令替换的指令)。考虑到正确性和安全风险,这是一个难以推荐的事情。 - Charles Duffy
2个回答

4
&&并没有被转义,只是在简单命令中没有特殊含义。当你写下如下命令时:
foo && bar

Bash解释为两个简单命令 - foobar,由控制运算符&&连接。但是当您像这样编写时:
cmd='foo && bar'
$cmd

您只需要一个简单的命令$cmd。Bash执行参数替换(将$cmd替换为foo && bar)和单词拆分(将foo && bar替换为foo && bar),但它不会搜索任何特殊字符,如&&>|'
要解决此问题,您需要使用不同的方法。在您的示例中,最好消除额外的间接性。
  cd "$ansible_dir" && ansible-playbook --extra-vars env="${ENV}" "${@}"

但在一个更加复杂的例子中,你可能会发现编写一个帮助函数很有用。


2
cmd="cd $ansible_dir && ..."

您不能在变量中构建这样的命令,只有在解释特殊语法(例如&&)之后才会展开变量。

但我看不出为什么您要这样做,直接执行cd命令不就可以了吗?

ansible_run() {
  ansible_dir=$(ansible_work_dir)
  cd $ansible_dir && ansible-playbook --extra-vars env="${ENV}" "$@"
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接