我有这个多行字符串(包括引号):
abc'asdf"
$(dont-execute-this)
foo"bar"''
我将如何分配它到一个变量使用heredoc在Bash?
我需要保留换行符。
我不想转义字符串中的字符,这将是恼人的…
我有这个多行字符串(包括引号):
abc'asdf"
$(dont-execute-this)
foo"bar"''
我将如何分配它到一个变量使用heredoc在Bash?
我需要保留换行符。
我不想转义字符串中的字符,这将是恼人的…
当前回答
$TEST="ok"
read MYTEXT <<EOT
this bash trick
should preserve
newlines $TEST
long live perl
EOT
echo -e $MYTEXT
其他回答
VAR=<<END
abc
END
不工作,因为你将stdin重定向到不关心它的东西,即赋值
export A=`cat <<END
sdfsdf
sdfsdf
sdfsfds
END
` ; echo $A
有用,但里面有个背部痉挛可能会阻止你使用这个。另外,你应该避免使用反引号,最好使用命令替换符号$(..)。
export A=$(cat <<END
sdfsdf
sdfsdf
sdfsfds
END
) ; echo $A
这里有一种非常优雅的方法,可以避免uoc:
VAR=$(sed -e 's/[ ]*\| //g' -e '1d;$d' <<'--------------------'
|
| <!DOCTYPE html>
| <html>
| <head>
| <script src='script.js'></script>
| </head>
| <body>
| <span id='hello-world'></span>
| </body>
| </html>
|
--------------------
)
'|'字符定义了空白,打印的字符串中只尊重空白右侧的空白。'1d;$d'去掉第一行和最后一行,它们只是作为内容周围的上下边距添加的。所有内容都可以缩进到您喜欢的任何级别,除了HEREDOC分隔符,在本例中它只是一堆连字符。
echo "$VAR"
# prints
<!DOCTYPE html>
<html>
<head>
<script src='script.js'></script>
</head>
<body>
<span id='hello-world'></span>
</body>
</html>
我发现自己必须读取一个NULL字符串,所以这里有一个解决方案,将读取任何你扔在它。虽然如果你实际上是在处理NULL,你将需要在十六进制级别上处理它。
$ cat > read.dd.sh
read.dd() {
buf=
while read; do
buf+=$REPLY
done < <( dd bs=1 2>/dev/null | xxd -p )
printf -v REPLY '%b' $( sed 's/../ \\\x&/g' <<< $buf )
}
证明:
$ . read.dd.sh
$ read.dd < read.dd.sh
$ echo -n "$REPLY" > read.dd.sh.copy
$ diff read.dd.sh read.dd.sh.copy || echo "File are different"
$
这里的例子(有^J, ^M, ^I):
$ read.dd <<'HEREDOC'
> (TAB)
> (SPACES)
(^J)^M(^M)
> DONE
>
> HEREDOC
$ declare -p REPLY
declare -- REPLY=" (TAB)
(SPACES)
(^M)
DONE
"
$ declare -p REPLY | xxd
0000000: 6465 636c 6172 6520 2d2d 2052 4550 4c59 declare -- REPLY
0000010: 3d22 0928 5441 4229 0a20 2020 2020 2028 =".(TAB). (
0000020: 5350 4143 4553 290a 285e 4a29 0d28 5e4d SPACES).(^J).(^M
0000030: 290a 444f 4e45 0a0a 220a ).DONE
从尼尔的回答来看,你通常根本不需要var,你可以像使用变量一样使用函数,而且它比内联或基于读取的解决方案更容易读取。
$ complex_message() {
cat <<'EOF'
abc'asdf"
$(dont-execute-this)
foo"bar"''
EOF
}
$ echo "This is a $(complex_message)"
This is a abc'asdf"
$(dont-execute-this)
foo"bar"''
你可以避免无用的cat使用,并更好地处理不匹配的引号:
$ read -r -d '' VAR <<'EOF'
abc'asdf"
$(dont-execute-this)
foo"bar"''
EOF
如果回显时不引用变量,则会丢失换行符。引用它来保存它们:
$ echo "$VAR"
abc'asdf"
$(dont-execute-this)
foo"bar"''
如果您想在源代码中使用缩进来提高可读性,请在小于号之后使用破折号。缩进必须只使用制表符(没有空格)。
$ read -r -d '' VAR <<-'EOF'
abc'asdf"
$(dont-execute-this)
foo"bar"''
EOF
$ echo "$VAR"
abc'asdf"
$(dont-execute-this)
foo"bar"''
相反,如果希望保留结果变量内容中的制表符,则需要从IFS中删除制表符。这里文档(EOF)的终端标记不能缩进。
$ IFS='' read -r -d '' VAR <<'EOF'
abc'asdf"
$(dont-execute-this)
foo"bar"''
EOF
$ echo "$VAR"
abc'asdf"
$(dont-execute-this)
foo"bar"''
通过按Ctrl-V Tab可以在命令行中插入选项卡。如果您正在使用编辑器,这取决于哪种编辑器,也可以工作,或者您可能必须关闭自动将制表符转换为空格的功能。