如何将一个heredoc值分配给Bash中的variables?
我有这个多行string(包括引号):
abc'asdf" $(dont-execute-this) foo"bar"''
我如何将它分配给variables在Bash中使用heredoc?
我需要保留换行符。
我不想逃避string中的字符,这将是烦人的…
你可以避免一个无用的cat
使用和更好地处理不匹配的引号:
$ read -r -d '' VAR <<'EOF' abc'asdf" $(dont-execute-this) foo"bar"'' EOF
如果在回显variables时不引用variables,则换行符将丢失。 引用它保留了它们:
$ echo "$VAR" abc'asdf" $(dont-execute-this) foo"bar"''
如果您想在源代码中使用缩进以提高可读性,请在减less语句之后使用短划线。 缩进必须只使用制表符(不能有空格)。
$ read -r -d '' VAR <<-'EOF' abc'asdf" $(dont-execute-this) foo"bar"'' EOF $ echo "$VAR" abc'asdf" $(dont-execute-this) foo"bar"''
相反,如果您想要保留结果variables内容中的选项卡,则需要从IFS
删除选项卡。 这里doc( EOF
)的terminal标记不能缩进。
$ IFS='' read -r -d '' VAR <<'EOF' abc'asdf" $(dont-execute-this) foo"bar"'' EOF $ echo "$VAR" abc'asdf" $(dont-execute-this) foo"bar"''
通过按Ctrl – V Tab键,可以在命令行插入标签 。 如果您使用的是编辑器,则取决于哪一个编辑器也可以工作,或者您可能不得不closures自动将制表符转换为空格的function。
使用$()将cat
的输出分配给您的variables,如下所示:
VAR=$(cat <<'END_HEREDOC' abc'asdf" $(dont-execute-this) foo"bar"'' END_HEREDOC ) echo "$VAR"
确保使用单引号分隔END_HEREDOC。
感谢@ephemient
的答案。
这是Dennis方法的变体,在脚本中看起来更优雅。
function定义:
define(){ IFS='\n' read -r -d '' ${1} || true; }
用法:
define VAR <<'EOF' abc'asdf" $(dont-execute-this) foo"bar"'' EOF echo "$VAR"
请享用
ps为不支持read -d
shell创build了“读循环”版本。 应该使用set -eu
和不成对的反引号 ,但是没有很好的testing:
define(){ o=; while IFS="\n" read -ra; do o="$o$a"' '; done; eval "$1=\$o"; }
VAR=<<END abc END
不起作用,因为你正在将stdinredirect到不关心它的事情上,即赋值
export A=`cat <<END sdfsdf sdfsdf sdfsfds END ` ; echo $A
工作,但是有一个在那里可能会阻止你使用这个back-tic。 另外,你应该避免使用反引号,最好使用命令replace符$(..)
。
export A=$(cat <<END sdfsdf sdfsdf sdfsfds END ) ; echo $A
在这里添加评论作为答案,因为我没有足够的代表点来评论你的问题文本。
仍然没有解决scheme,保留换行符。
这不是真的 – 你可能只是被回声的行为误导了:
echo $VAR # strips newlines
echo "$VAR" # preserves newlines
分配一个heredoc值给一个variables
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 )"
一个数组是一个variables,所以在这种情况下mapfile将工作
mapfile y <<z abc'asdf" $(dont-execute-this) foo"bar"'' z
然后你可以打印这样的
printf %s "${y[@]}"
Neil的答案分支,你通常不需要一个变种,你可以使用一个函数在很大程度上作为一个variables,它比内联或基于read
的解决scheme更容易阅读。
$ 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"''
我发现自己不得不阅读一个NULL的string,所以这里是一个解决scheme,将读取任何你扔在它。 虽然如果你实际上正在处理NULL,你将需要在hex级别处理。
$ 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 ) }
certificate:
$ . 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):
$ 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的回答 ,这显示了他伟大的解决scheme是如何工作的,并且表明你可以很容易地在文本中引用引号和variables:
示例输出
$ ./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
$TEST="ok" read MYTEXT <<EOT this bash trick should preserve newlines $TEST long live perl EOT echo -e $MYTEXT