我有这个多行字符串(包括引号):
abc'asdf"
$(dont-execute-this)
foo"bar"''
我将如何分配它到一个变量使用heredoc在Bash?
我需要保留换行符。
我不想转义字符串中的字符,这将是恼人的…
我有这个多行字符串(包括引号):
abc'asdf"
$(dont-execute-this)
foo"bar"''
我将如何分配它到一个变量使用heredoc在Bash?
我需要保留换行符。
我不想转义字符串中的字符,这将是恼人的…
当前回答
将heredoc值赋给变量
VAR="$(cat <<'VAREOF'
abc'asdf"
$(dont-execute-this)
foo"bar"''
VAREOF
)"
用作命令的参数
echo "$(cat <<'SQLEOF'
xxx''xxx'xxx'xx 123123 123123
abc'asdf"
$(dont-execute-this)
foo"bar"''
SQLEOF
)"
其他回答
这是Dennis方法的变化,在脚本中看起来更优雅。
函数定义:
define(){ IFS='\n' read -r -d '' ${1} || true; }
用法:
define VAR <<'EOF'
abc'asdf"
$(dont-execute-this)
foo"bar"''
EOF
echo "$VAR"
享受
附注:为不支持read -d的shell创建了一个“read循环”版本。应该适用于set -eu和未配对的反引号,但测试不太好:
define(){ o=; while IFS="\n" read -r a; do o="$o$a"'
'; done; eval "$1=\$o"; }
真不敢相信我是第一个发这个的人。
@Erman和@Zombo很接近,但mapfile不只是读取数组…
考虑一下:
#!/bin/bash
mapfile -d '' EXAMPLE << 'EOF'
Hello
こんにちは
今晩は
小夜なら
EOF
echo -n "$EXAMPLE"
收益率:
Hello こんにちは 今晩は 小夜なら
$ "是给mapfile的分隔符,它永远不会出现,它意味着“未分隔”。
因此,不需要无用地使用cat,也不需要重新组合数组。
此外,你还能得到这样的好处:
$ echo $EXAMPLE
Hello こんにちは 今晩は 小夜なら
你没有收到@Zombo的方法:
mapfile y <<'z'
abc'asdf"
$(dont-execute-this)
foo"bar"''
z
echo $y
abc'asdf"
奖金
如果你通过head -c -1运行它,你也可以用一种不会不性能的方式摆脱最后的换行:
unset EXAMPLE
mapfile -d '' EXAMPLE < <(head -c -1 << EOF
Hello
こんにちは
今晩は
小夜なら
EOF
)
printf "%q" "$EXAMPLE"
$'Hello\nこんにちは\n今晩は\n小夜なら'
感谢dimo414的回答,这展示了他的伟大解决方案是如何工作的,并表明你可以在文本中轻松地使用引号和变量:
示例输出
$ ./test.sh
The text from the example function is:
Welcome dev: Would you "like" to know how many 'files' there are in /tmp?
There are " 38" files in /tmp, according to the "wc" command
test.sh
#!/bin/bash
function text1()
{
COUNT=$(\ls /tmp | wc -l)
cat <<EOF
$1 Would you "like" to know how many 'files' there are in /tmp?
There are "$COUNT" files in /tmp, according to the "wc" command
EOF
}
function main()
{
OUT=$(text1 "Welcome dev:")
echo "The text from the example function is: $OUT"
}
main
我发现自己必须读取一个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=<<END
abc
END
不工作,因为你将stdin重定向到不关心它的东西,即赋值
export A=`cat <<END
sdfsdf
sdfsdf
sdfsfds
END
` ; echo $A
有用,但里面有个背部痉挛可能会阻止你使用这个。另外,你应该避免使用反引号,最好使用命令替换符号$(..)。
export A=$(cat <<END
sdfsdf
sdfsdf
sdfsfds
END
) ; echo $A