How to assign a string value to a variable over multiple lines while indented?
Here the issue is that you are surrounding the variable with double quotes (""). Remove it and things will work fine.
VAR="This displays with \
extra spaces."
echo ${VAR}
Output
This displays with extra spaces.
Here the issue is that double quoting a variable preserves all white space characters. This can be used in case if you explicitly need it.
For example,
$ echo "Hello World ........ ... ...."
will print
Hello World ........ ... ....
And on removing quotes, its different
$ echo Hello World ........ ... ....
Hello World ........ ... ....
Here the Bash removes extra spaces in the text because in the first case the entire text is taken as a "single" argument and thus preserving extra spaces.
But in the second case echo
command receives the text as 5 arguments.
Quoting a variable will also be helpful while passing arguments to commands.
In the below command, echo
only gets single argument as "Hello World"
$ variable="Hello World"
$ echo "$variable"
But in case of the below scenario echo
gets two arguments as Hello
and World
$ variable="Hello World"
$ echo $variable
The solutions given by esuoxu and Mickaël Bucas are the common and more portable ways of doing this.
Here are a few bash
solutions (some of which should also work in other shells, like zsh
). Firstly with the +=
append operator (which works in a slightly different way for each of an integer variable, a regular variable and an array).
text="Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod "
text+="tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, "
text+="quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea ..."
If you want newlines (or other whitespace/escapes) in the text, use $''
quoting instead:
text=$'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod\n'
text+=$'...'
Next, using printf -v
to assign a formatted value to a variable
printf -v text "%s" "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed " \
"do eiusmod empor incididunt ut labore et dolore magna aliqua. "\
"Ut enim ad minim veniam ..."
The trick here is that there are more arguments than format specifiers, so unlike most printf
functions, the bash one reuses the format string until it runs out. You can put a \n
within the format string, or use $'', (or both) to deal with whitespace.
Next, using an array:
text=("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod "
"tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, "
"quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea ..." )
You can also use +=
to build the text up line by line (note the ()
):
text+=("post script")
Here though, you must remember to "flatten" the array if you want the entire text content in one go
echo "$text" # only outputs index [0], the first line
echo "${text[*]}" # output complete text (joined by first character of IFS)
(integer indexed arrays are implicitly sorted, unlike associative arrays) This gives you slightly more flexibility since you can manipulate lines and even slice and dice if needed.
Finally, using read
or readarray
and a "here-document":
read -r -d '' text <<-"EOT"
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea ...
EOT
readarray -t textarray <<-"EOT"
Lorem [...]
EOT
The here-document form of <<-
means all leading hard tabs are removed from the input, so you must use tabs to indent your text. Quotes around "EOT"
prevent shell expansion features, so the input is used verbatim.
With read
it uses NUL byte delimited input, so that it will read the newline delimited text in one go. With readarray
(aka mapfile
, available since bash-4.0) it reads into an array, and -t
strips newlines on each line.
There is a special heredoc syntax that removes tabs at the beginning of all lines : "<<-" (notice the dash added)
http://tldp.org/LDP/abs/html/here-docs.html
Example 19-4. Multi-line message, with tabs suppressed
You can use it like this :
v="$(cat <<-EOF
A
B
C
EOF
)"
echo "$v"
Result :
A
B
C
It works only with tabs, not spaces.