How to assign a heredoc value to a variable in Bash?
我有这个多行字符串(包括引号):
1 2 3 | abc'asdf" $(dont-execute-this) foo"bar"'' |
如何使用bash中的heredoc将其分配给变量?
我需要保留新行。
我不想逃避字符串中的字符,那会很烦人…
您可以避免使用
1 2 3 4 5 | $ read -r -d '' VAR <<'EOF' abc'asdf" $(dont-execute-this) foo"bar"'' EOF |
如果在回送变量时不引用它,新行将丢失。引用它可以保护它们:
1 2 3 4 | $ echo"$VAR" abc'asdf" $(dont-execute-this) foo"bar"'' |
如果要在源代码中使用缩进来提高可读性,请在小于号后使用破折号。只能使用制表符(无空格)进行缩进。
1 2 3 4 5 6 7 8 9 | $ read -r -d '' VAR <<-'EOF' abc'asdf" $(dont-execute-this) foo"bar"'' EOF $ echo"$VAR" abc'asdf" $(dont-execute-this) foo"bar"'' |
如果您希望保留结果变量内容中的制表符,则需要从
1 2 3 4 5 6 7 8 9 | $ IFS='' read -r -d '' VAR <<'EOF' abc'asdf" $(dont-execute-this) foo"bar"'' EOF $ echo"$VAR" abc'asdf" $(dont-execute-this) foo"bar"'' |
通过按ctrl vbkbd t,可以在命令行插入选项卡。如果您使用的编辑器取决于哪个编辑器,它也可以工作,或者您可能需要关闭自动将制表符转换为空格的功能。
使用$()将
1 2 3 4 5 6 7 8 9 10 11 | 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 |
确保用单引号分隔起始和结束文档。
注意,结束Heredoc分隔符
感谢
这是丹尼斯方法的变体,在脚本中看起来更优雅。
函数定义:
1 2 | define(){ IFS=' ' read -r -d '' ${1} || true; } |
用途:
1 2 3 4 5 6 7 | define VAR <<'EOF' abc'asdf" $(dont-execute-this) foo"bar"'' EOF echo"$VAR" |
享受
P.S.为不支持
1 2 3 | define(){ o=; while IFS=" " read -r a; do o="$o$a"' '; done; eval"$1=\$o"; } |
在此处添加评论作为答案,因为我没有足够的代表点来评论您的问题文本。
There is still no solution that preserves newlines.
这不是真的-你可能只是被回声的行为误导了:
1 2 3 | VAR=<<END abc END |
不起作用,因为您正在将stdin重定向到不关心它的内容,即分配
1 2 3 4 5 6 | export A=`cat <<END sdfsdf sdfsdf sdfsfds END ` ; echo $A |
有效,但有一个背后的抽搐,可能会阻止你使用这个。另外,您应该避免使用反勾号,最好使用命令替换符号
1 2 3 4 5 6 | export A=$(cat <<END sdfsdf sdfsdf sdfsfds END ) ; echo $A |
从Neil的答案出发,您通常根本不需要var,您可以以与变量相同的方式使用函数,而且它比内联或基于
1 2 3 4 5 6 7 8 9 10 11 12 | $ 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"'' |
数组是一个变量,因此在这种情况下,mapfile可以工作
1 2 3 4 5 | mapfile y <<z abc'asdf" $(dont-execute-this) foo"bar"'' z |
然后你可以这样打印
1 | printf %s"${y[@]}" |
将HereDoc值赋给变量
1 2 3 4 5 6 | VAR="$(cat <<'VAREOF' abc'asdf" $(dont-execute-this) foo"bar"'' VAREOF )" |
用作命令的参数
1 2 3 4 5 6 7 | echo"$(cat <<'SQLEOF' xxx''xxx'xxx'xx 123123 123123 abc'asdf" $(dont-execute-this) foo"bar"'' SQLEOF )" |
我发现自己必须读取一个包含空值的字符串,所以这里有一个解决方案,可以读取任何您向它抛出的内容。尽管您实际上处理的是空值,但您需要在十六进制级别处理它。
$cat>读.dd.sh
1 2 3 4 5 6 7 8 | 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 ) } |
证明:
1 2 3 4 5 | $ . 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" $ |
Heredoc示例(带^J、^M、^I):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | $ 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 |
由于dimo414的回答,这显示了他伟大的解决方案是如何工作的,并且显示了文本中也可以轻松地包含引号和变量:
实例输出1 2 3 4 5 6 | $ ./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 |
试验室
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | #!/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 |
1 2 3 4 5 6 7 8 | $TEST="ok" read MYTEXT <<EOT this bash trick should preserve newlines $TEST long live perl EOT echo -e $MYTEXT |