bash heredoc可以将其结果直接放入变量中吗? [英] Can a bash heredoc put its result directly into a variable?
问题描述
我有一些类似这样的代码:
I have some code like this:
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中的变量,而无需进行干预(cat)?该代码有效,只是感觉工作太多.
is there a way to get a here doc to assign result directly to variable in bash without intervening process (cat)? This code works, it just feels like too much work.
推荐答案
如何将here-string放入Bash中的变量:
How to put a here-string into a variable in Bash:
在Bash中,将 -d
分隔符设置为null的情况下,使用 read
:
In Bash use read
with the -d
delimiter set to null:
IFS= read -r -d '' cmd <<EOC
...blah blah...
EOC
请确保您确实在 read
前面使用了如图所示的 IFS =
,否则所有前导和尾随空格都会被剪裁.确保使用 -r
,否则某些反斜杠将被理解为转义反斜杠.
Make sure you really use IFS=
like shown, in front of read
, otherwise any leading and trailing spaces will be trimmed. Make sure you use -r
otherwise some backslashes would be understood as escape backslashes.
有人会认为,仅将简单分配用于以下内容会更简单:
Some would argue that it's simpler to just use a plain assignment as:
cmd='
...blah blah...
'
但是有时您会引号很多,以至于使用它变得越来越简单.
But sometimes you have lots of quotes to the point that it becomes simpler and nicer to use this.
细微的注释.这样,由于未在EOF之前读取空字节定界符,因此 read
返回失败返回码(1).虽然大多数时候都可以,但是如果您使用 set -e
(但您真的不应该使用 set -e
).如果要确定,请添加:
Subtle note. With this, read
returns a failure return code (1) since the null-byte delimiter is not read before EOF. While this is alright most of the times, it can be a problem if you're using set -e
(but you really shouldn't use set -e
anyway). If you want to be sure, add:
IFS= read -r -d '' cmd <<EOC || true
...blah blah...
EOC
现在,认真对待您的问题.
下面是一个严重的提示,您确实应该考虑:请勿将代码放入字符串中!它坏了!.而是使用函数或数组(仍然很差,但不会损坏).这是使用数组的方式:
Now, seriously, about your problem.
Below is a serious note that you really should take into account: don't put code into strings! it's broken!. Instead, use a function or (still bad, but not broken) an array. Here's how you would use an array:
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"
)
(用爱心观察我花时间键入的引号).然后,您可以安全地运行它(如果您的参数中包含全局字符,引号或空格,则可以安全地运行它):
(observe the quotes that I took time to type, with love). Then you can safely run it (by safely I mean it's all right if you're having glob characters or quotes or spaces in your arguments) as:
"${mycommand[@]}"
(再次观察健康的报价).如果要打印命令,请使用以下命令:
(observe the healthy quotes, again). If you want to print the command, use this:
printf '%s\n' "${mycommand[*]}"
不幸的是,这里不会保留换行符.但实际上,这根本不是问题.如果确实需要,则应通过某种格式程序传递此命令(很可能它不存在,因此您必须自己编写代码).但是将事情摆放正确:您想定义一个命令来执行它(并有选择地格式化它,以供用户显示),而不是相反,要有一个很好的字符串然后您必须(危险地)解析用户的眼睛才能转换为代码.
Unfortunately, the line breaks won't be preserved here. But really, that shouldn't be a problem at all. If really needed, you should pass this command through a formatter of some sort (well, very likely it doesn't exist so you'll have to code it yourself). But put the things in the right order: you want to define a command, to execute it (and, optionally format it, for user display), not the other way round, have a string that's nice to the user's eyes that you then have to parse (dangerously) to transform into code.
这篇关于bash heredoc可以将其结果直接放入变量中吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!