我有这个多行字符串(包括引号):
abc'asdf"
$(dont-execute-this)
foo"bar"''
我将如何分配它到一个变量使用heredoc在Bash?
我需要保留换行符。
我不想转义字符串中的字符,这将是恼人的…
我有这个多行字符串(包括引号):
abc'asdf"
$(dont-execute-this)
foo"bar"''
我将如何分配它到一个变量使用heredoc在Bash?
我需要保留换行符。
我不想转义字符串中的字符,这将是恼人的…
当前回答
这是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"; }
其他回答
仍然没有保留换行符的解决方案。
这不是真的——你可能只是被echo的行为误导了:
返回$VAR #换行符
echo "$VAR" #保留换行符
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
使用$()将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的回答。
从尼尔的回答来看,你通常根本不需要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"''
这里有一种非常优雅的方法,可以避免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>