我有这个多行字符串(包括引号):

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

感谢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

使用$()将cat的输出赋值给你的变量,如下所示:

VAR=$(cat <<'END_HEREDOC'
abc'asdf"
$(dont-execute-this)
foo"bar"''
END_HEREDOC
)

# this will echo variable with new lines intact
echo "$VAR"
# this will echo variable without new lines (changed to space character)
echo $VAR

确保从END_HEREDOC开始用单引号分隔。

注意,结束括号分隔符END_HEREDOC必须单独在一行上(因此结束括号在下一行上)。

感谢@ephemient的回答。

数组是一个变量,所以在这种情况下mapfile可以工作

mapfile y <<'z'
abc'asdf"
$(dont-execute-this)
foo"bar"''
z

然后你可以像这样打印

printf %s "${y[@]}"

这是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"; }