我有这个多行字符串(包括引号):
abc'asdf"
$(dont-execute-this)
foo"bar"''
Run Code Online (Sandbox Code Playgroud)
如何在Bash中使用heredoc将其分配给变量?
我需要保留换行符.
我不想逃避字符串中的字符,这会很烦人......
Pau*_*ce. 479
您可以使用以下方法避免无用的使用cat
和更好地处理不匹配的引号:
$ read -r -d '' VAR <<'EOF'
abc'asdf"
$(dont-execute-this)
foo"bar"''
EOF
Run Code Online (Sandbox Code Playgroud)
如果在回显变量时没有引用变量,则会丢失换行符.引用它保留了它们:
$ echo "$VAR"
abc'asdf"
$(dont-execute-this)
foo"bar"''
Run Code Online (Sandbox Code Playgroud)
如果您想在源代码中使用缩进以提高可读性,请在less-thans之后使用短划线.缩进必须仅使用制表符(无空格)完成.
$ read -r -d '' VAR <<-'EOF'
abc'asdf"
$(dont-execute-this)
foo"bar"''
EOF
$ echo "$VAR"
abc'asdf"
$(dont-execute-this)
foo"bar"''
Run Code Online (Sandbox Code Playgroud)
相反,如果要保留结果变量内容中的选项卡,则需要从中删除选项卡IFS
.此处doc(EOF
)的终端标记不得缩进.
$ IFS='' read -r -d '' VAR <<'EOF'
abc'asdf"
$(dont-execute-this)
foo"bar"''
EOF
$ echo "$VAR"
abc'asdf"
$(dont-execute-this)
foo"bar"''
Run Code Online (Sandbox Code Playgroud)
按Ctrl- 可以在命令行插入选项卡V Tab.如果您使用的是编辑器,则根据哪个编辑器可能也有效,或者您可能必须关闭自动将选项卡转换为空格的功能.
Nei*_*eil 217
使用$()将输出分配给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
Run Code Online (Sandbox Code Playgroud)
确保用单引号分隔起始END_HEREDOC.
请注意,结束heredoc分隔符END_HEREDOC
必须在行上单独(因此结束括号在下一行).
感谢您@ephemient
的回答.
ttt*_*ttt 77
这是Dennis方法的变体,在脚本中看起来更优雅.
功能定义:
define(){ IFS='\n' read -r -d '' ${1} || true; }
Run Code Online (Sandbox Code Playgroud)
用法:
define VAR <<'EOF'
abc'asdf"
$(dont-execute-this)
foo"bar"''
EOF
echo "$VAR"
Run Code Online (Sandbox Code Playgroud)
请享用
ps 为不支持的shell 创建了"读取循环"版本read -d
.应该使用set -eu
和不成对的反引号,但没有很好地测试:
define(){ o=; while IFS="\n" read -r a; do o="$o$a"'
'; done; eval "$1=\$o"; }
Run Code Online (Sandbox Code Playgroud)
pat*_*pam 33
在此添加评论作为答案,因为我没有足够的代表点来评论您的问题文本.
仍然没有解决方案可以保留换行符.
这不是真的 - 你可能只是被echo的行为误导了:
echo $VAR # strips newlines
echo "$VAR" # preserves newlines
l0s*_*t3d 30
VAR=<<END
abc
END
Run Code Online (Sandbox Code Playgroud)
因为你将stdin重定向到不关心它的东西,即赋值,所以不起作用
export A=`cat <<END
sdfsdf
sdfsdf
sdfsfds
END
` ; echo $A
Run Code Online (Sandbox Code Playgroud)
有效,但有一个背景可能会阻止你使用它.另外,你应该真的避免使用反引号,最好使用命令替换表示法$(..)
.
export A=$(cat <<END
sdfsdf
sdfsdf
sdfsfds
END
) ; echo $A
Run Code Online (Sandbox Code Playgroud)
dim*_*414 10
根据Neil的回答,您通常根本不需要var,您可以使用与变量大致相同的函数,并且它比内联或read
基于解决方案更容易阅读.
$ 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"''
Run Code Online (Sandbox Code Playgroud)
小智 9
数组是一个变量,因此在这种情况下mapfile将起作用
mapfile y <<z
abc'asdf"
$(dont-execute-this)
foo"bar"''
z
Run Code Online (Sandbox Code Playgroud)
然后你可以像这样打印
printf %s "${y[@]}"
Run Code Online (Sandbox Code Playgroud)
我不敢相信我是第一个发布此内容的人。
\n@Erman 和 @Zombo 很接近,但mapfile
不只是读取数组......
考虑一下:
\n#!/bin/bash\nmapfile -d \'\' EXAMPLE << \'EOF\'\nHello\n\xe3\x81\x93\xe3\x82\x93\xe3\x81\xab\xe3\x81\xa1\xe3\x81\xaf\n\xe4\xbb\x8a\xe6\x99\xa9\xe3\x81\xaf\n\xe5\xb0\x8f\xe5\xa4\x9c\xe3\x81\xaa\xe3\x82\x89\nEOF\necho -n "$EXAMPLE"\n
Run Code Online (Sandbox Code Playgroud)\n产量:
\n\n你好\n\xe3\x81\x93\xe3\x82\x93\xe3\x81\xab\xe3\x81\xa1\xe3\x81\xaf\n\xe4\xbb\x8a\xe6\x99\xa9\xe3 \x81\xaf\n\xe5\xb0\x8f\xe5\xa4\x9c\xe3\x81\xaa\xe3\x82\x89\n\n
$\'\'
是给 的分隔符mapfile
,它永远不会出现,意味着“未分隔”。
因此,不需要无用地使用数组cat
,也不需要承受重新组合数组的惩罚。
此外,您还可以获得以下好处:
\n\nHello\n\xe3\x81\x93\xe3\x82\x93\xe3\x81\xab\xe3\x81\xa1\xe3\x81\xaf\n\xe4\xbb\x8a\xe6\x99\xa9\xe3\x81\xaf\n\xe5\xb0\x8f\xe5\xa4\x9c\xe3\x81\xaa\xe3\x82\x89\n\n
您通过@Zombo\'s 方法没有收到:
\n$ echo $EXAMPLE\nHello \xe3\x81\x93\xe3\x82\x93\xe3\x81\xab\xe3\x81\xa1\xe3\x81\xaf \xe4\xbb\x8a\xe6\x99\xa9\xe3\x81\xaf \xe5\xb0\x8f\xe5\xa4\x9c\xe3\x81\xaa\xe3\x82\x89\n
Run Code Online (Sandbox Code Playgroud)\n\nabc\'asdf"\n\n
如果你运行它,head -c -1
你还可以以一种不会表现不佳的方式摆脱最后一个换行符:
mapfile y <<\'z\'\nabc\'asdf"\n$(dont-execute-this)\nfoo"bar"\'\'\nz\necho $y\n
Run Code Online (Sandbox Code Playgroud)\n\nabc\'asdf"\n\n