bash heredoc可以将其结果直接放入变量吗?

时间:2015-02-17 16:00:15

标签: 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/server-key.pem --peer-ca-file=/cert/ca.pem 
   --peer-addr=$MY_IP:$PEER_PORT 
   --peers=$OIPPC
EOC
)

有没有办法让这里的doc直接将结果分配给bash中的变量而不需要介入进程(cat)?这段代码有效,只是感觉太多了。

1 个答案:

答案 0 :(得分:2)

  

如何将here-string放入Bash中的变量:

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

IFS= read -r -d '' cmd <<EOC
    ...blah blah...
EOC

确保在IFS=前面确实使用了read,否则将修剪任何前导和尾随空格。确保使用-r,否则一些反斜杠将被理解为转义反斜杠。

有些人认为使用普通作业更简单:

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

但有时你会有很多引用,以至于使用它会变得更简单和更好。

微妙的注释。这样,read返回失败返回码(1),因为在EOF之前未读取空字节定界符。虽然大部分时间都没问题,但如果您使用的是set -eyou really shouldn't use set -e anyway),则可能会出现问题。如果您想确定,请添加:

IFS= read -r -d '' cmd <<EOC || true
    ...blah blah...
EOC

现在,严肃地说,关于你的问题。

下面是一个严肃的说明,你真的应该考虑:不要把代码放到字符串中! it's broken!。相反,使用一个函数或(仍然坏,但没有破坏)数组。以下是使用数组的方法:

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[*]}"

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