I have this multiline string (including quotes):
abc'asdf" $(dont-execute-this) foo"bar"''
How to use Heredoc to assign variables in Bash?
I need to keep line breaks.
I don't want to escape characters in strings, which is annoying
#1 building
I find myself having to read the string that contains NULL, so this is a solution that will read anything you throw in it. Although if you are actually dealing with NULL, you will need to do so at the hexadecimal level.
$ 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 ) }
Prove:
$ . 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 example (with ^ 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
#2 building
VAR=<<END abc END
It doesn't work because you redirect standard input to something unrelated, that is, assignment
export A=`cat <<END sdfsdf sdfsdf sdfsfds END ` ; echo $A
Yes, but there is a small problem that may prevent you from using it. In addition, you should avoid using backquotes, preferably using the command to replace the symbol $(..).
export A=$(cat <<END sdfsdf sdfsdf sdfsfds END ) ; echo $A
#3 building
Use $() to assign the output of cat to your variable as follows:
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
Make sure to separate the beginning of end ﹣ heredoc with single quotes.
Note that the end of this line delimiter end ﹣ heredoc must exist alone (therefore, the end of the parenthesis is on the next line).
Thank you @ ehemient for your answer.
#4 building
$TEST="ok" read MYTEXT <<EOT this bash trick should preserve newlines $TEST long live perl EOT echo -e $MYTEXT
#5 building
You can use the following methods to avoid unnecessary use of cat and better handle mismatched quotes:
$ read -r -d '' VAR <<'EOF' abc'asdf" $(dont-execute-this) foo"bar"'' EOF
If you echo a variable without referring to it, the newline character is lost. Reference it to keep them:
$ echo "$VAR" abc'asdf" $(dont-execute-this) foo"bar"''
If you want to use indentation in your source code to improve readability, use a dash after the less than sign. Indentation must be done using only tabs (no spaces).
$ read -r -d '' VAR <<-'EOF' abc'asdf" $(dont-execute-this) foo"bar"'' EOF $ echo "$VAR" abc'asdf" $(dont-execute-this) foo"bar"''
Instead, if you want to keep the tabs in the contents of the result variable, you need to remove the tabs from IFS. Terminal tags for EOF should not be indented here.
$ IFS='' read -r -d '' VAR <<'EOF' abc'asdf" $(dont-execute-this) foo"bar"'' EOF $ echo "$VAR" abc'asdf" $(dont-execute-this) foo"bar"''
You can insert tabs on the command line by pressing Ctrl - V Tab. If you are using an editor (depending on which one), it may also work, or you may have to turn off the ability to automatically convert tabs to spaces.