bash-herdoc能否将其结果直接放入变量中?

bash-herdoc能否将其结果直接放入变量中?,bash,Bash,我有一些这样的代码: 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/s

我有一些这样的代码:

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
)
CMD=$(cat)
如何在Bash中将here字符串放入变量中:

在Bash中,使用
read
,并将
-d
分隔符设置为null:

IFS= read -r -d '' cmd <<EOC
    ...blah blah...
EOC
但有时你会引用很多的话,以至于使用它会变得更简单、更好

微妙提示。使用此功能,
read
返回失败返回代码(1),因为在EOF之前未读取空字节分隔符。虽然大多数情况下这是正常的,但如果使用
set-e
(但是),则可能会出现问题。如果要确定,请添加:

IFS= read -r -d '' cmd <<EOC || true
    ...blah blah...
EOC
(注意我花时间输入的引语,带着爱)。 然后您可以安全地运行它(安全地说,我的意思是,如果您的参数中有glob字符、引号或空格,那么就可以了),如下所示:

(再次观察正确的引号)。如果要打印命令,请使用以下命令:

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

不幸的是,这里不会保留换行符。但实际上,这根本不应该是一个问题。如果真的需要,您应该通过某种形式的格式化程序传递此命令(很可能它不存在,所以您必须自己编写代码)。但请按正确的顺序排列:您要定义一个命令,然后执行它(并且,为了用户显示,可以选择对其进行格式化),而不是相反,使用一个对用户眼睛很好的字符串,然后您必须(危险地)解析该字符串以转换为代码。

为什么在这里使用herdoc?如果您只想在
CMD
变量中使用该字符串(顺便说一句,您不需要,请参阅原因)然后直接使用带引号的字符串
CMD=“docker run…”
。感谢指针。我使用herdoc是因为我想回显命令(如果调用程序请求verbose),记录命令,最后运行它。我已经习惯了python/perl中的herdoc,并且对它们很熟悉。我发现它们使用起来是错误的。herdoc与回显命令有什么关系?对变量的赋值让您可以不必担心。另外,
set-x
可能是一种更好的
verbose
模式手动回显命令(尽管有时会更加冗长,阅读起来也有点奇怪)。
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"
)
"${mycommand[@]}"
printf '%s\n' "${mycommand[*]}"