一个bash heredoc能否将其结果直接放入一个变量中?

9

我有一些类似这样的代码:

CMD=$(cat <<EOC
docker run 
   -p $MY_IP:$LOCAL_PORT:$LOCAL_PORT -p $MY_IP:$PEER_PORT:$PEER_PORT 
   -v $CERT_DIR:/cert 
   $ETCD_IMAGE 
   --name $MACHINE.$DOMAIN 
   --peer-cert-file=/cert/server-cert.pem
   --peer-key-file=/cert/server-key.pem --peer-ca-file=/cert/ca.pem 
   --peer-addr=$MY_IP:$PEER_PORT 
   --peers=$OIPPC
EOC
)

有没有一种方法在Bash中使用Here Doc将结果直接赋值给变量,而不需要介入进程(cat)?这段代码有效,但感觉有些繁琐。

1
你为什么要在这里使用heredoc?如果你只是想把那个字符串放到CMD变量中(顺便说一下,你不需要这样做,请参考http://mywiki.wooledge.org/BashFAQ/001),那么直接使用带引号的字符串即可,如`CMD="docker run ...."`。 - Etan Reisner
谢谢指针。我正在使用heredoc,因为我想回显命令(如果调用者请求详细信息),记录命令,最后运行它。我习惯于使用Python/Perl中的heredocs并对其感到舒适。我现在看到它们不适合使用。 - Greg
1
一个 heredoc 与 echo 命令有什么关系?变量的赋值可以让你不必使用 echo 命令。此外,set -x 很可能比手动 echo 命令具有更好的 verbose 模式 (虽然更加冗长,并且在某些情况下阅读起来有些奇怪)。 - Etan Reisner
1个回答

23
如何在Bash中将here-string放入变量中:
在Bash中使用read,将-d分隔符设置为null:
IFS= read -r -d '' cmd <<EOC
    ...blah blah...
EOC

请确保在read前使用如下的IFS=,否则会去除任何开头和结尾的空格。请确保使用-r,否则一些反斜杠会被理解为转义反斜杠。

有人可能会认为只需使用普通赋值更简单:

cmd='
    ...blah blah...
'

但有时你有很多引用,以至于使用这个会变得更加简单和好看。
微妙的说明。使用此选项,由于未在EOF之前读取空字节分隔符,read将返回一个失败的返回代码(1)。虽然大多数情况下这是没问题的,但如果你正在使用set -e (但你真的不应该使用set -e),那么这可能会成为一个问题。如果你想要确定,可以添加:
IFS= read -r -d '' cmd <<EOC || true
    ...blah blah...
EOC

现在,认真地谈谈你的问题。

以下是一条非常重要的提示:不要把代码放进字符串中!它会出错!。相反,使用函数或(虽然不好,但不会出错)数组。以下是如何使用数组:

mycommand=(
    docker run 
        -p "$MY_IP:$LOCAL_PORT:$LOCAL_PORT"
        -p "$MY_IP:$PEER_PORT:$PEER_PORT"
        -v "$CERT_DIR":/cert
        "$ETCD_IMAGE"
        --name "$MACHINE.$DOMAIN"
        --peer-cert-file=/cert/server-cert.pem
        --peer-key-file=/cert/server-key.pem
        --peer-ca-file=/cert/ca.pem 
        --peer-addr="$MY_IP:$PEER_PORT"
        --peers="$OIPPC"
)

(注意我费心打出的引号,带着爱)。 然后你可以安全地运行它(安全地运行是指如果你在参数中有glob字符、引号或空格也没关系),如下所示:

"${mycommand[@]}"

注意正确使用引号。如果想要打印命令,请使用以下代码:

printf '%s\n' "${mycommand[*]}"

很遗憾,这里无法保留换行符。但实际上,这应该不是什么问题。如果真的需要,你应该通过某种格式化程序(或许它不存在,所以你需要自己编写)来传递此命令。但要按照正确顺序进行:你需要定义一个命令,执行它(并且可选地对其进行格式化,以供用户显示),而不是反过来,先有一个对用户友好的字符串,然后必须解析(危险地)以将其转换为代码。

请保重,亲爱的 @gniourf_gniourf... 用爱心... - undefined

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