我在 bash 中引用时遇到了一个明显的问题,以至于我一时无法真正解决。这是一个通过 ssh 在远程服务器上的 sudo-subshell 中执行远程命令的循环:
for HOST in $RUNNER_LIST; do
ssh -t $HOST "sudo bash -c \"sed -i '$a 10.10.40.29 myhost' /etc/hosts\""
done 2>/dev/null
现在,这种简单的方法当然行不通了。它$a
会被本地 shell 扩展,并且由于这是一个未设置的变量,sed 会执行表达式' 10.10.40.29 myhost'
我尝试了几种方法,在写这个问题的过程中,我发现这种方法是有效的:
ssh -t $HOST "sudo bash -c \"sed -i '"'\$'"a 10.10.40.29 myhost' /etc/hosts\""
并使用 prepended set -x
,我看到在远程 shell 上它被扩展为
sudo bash -c 'sed '\''$a 10.10.40.29 myhost'\'' /etc/hosts'
我很惊讶,因为我的本意是转义$
。但结果却把引号转义了。所以我想清楚地解释一下这个扩展是如何工作的。也许有办法让这个命令更具可读性?
答案1
这并没有真正回答你的问题(我确实读你的帖子太快了,抱歉);要正确地做你想做的事情,你需要双重转义$
(forsed
和 for bash
) :
for HOST in $RUNNER_LIST; do
ssh -t $HOST "sudo bash -c \"sed -i '\\\$a 10.10.40.29 myhost' /tmp/hosts\""
done 2>/dev/null
如果没有bash -c
,则只需要一个级别:
for HOST in $RUNNER_LIST; do
ssh -t $HOST "sudo sed -i '\$a 10.10.40.29 myhost' /tmp/hosts"
done 2>/dev/null