How to specify a multi-line shell variable?

BashShell

Bash Problem Overview


I have written a query:

function print_ui_hosts
{
local sql = "select ........."
print_sql "$ sql"
}

local sql - a very long string. Query is not formatted. How can I split a string into multiple lines?

Bash Solutions


Solution 1 - Bash

simply insert new line where necessary

sql="
SELECT c1, c2
from Table1, Table2
where ...
"

shell will be looking for the closing quotation mark

Solution 2 - Bash

Use read with a heredoc as shown below:

read -d '' sql << EOF
select c1, c2 from foo
where c1='something'
EOF

echo "$sql"

Solution 3 - Bash

I would like to give one additional answer, while the other ones will suffice in most cases.

I wanted to write a string over multiple lines, but its contents needed to be single-line.

sql="                       \
SELECT c1, c2               \
from Table1, ${TABLE2}      \
where ...                   \
"

I am sorry if this if a bit off-topic (I did not need this for SQL). However, this post comes up among the first results when searching for multi-line shell variables and an additional answer seemed appropriate.

Solution 4 - Bash

Thanks to dimo414's answer to a similar question, this shows how his great solution works, and shows that you can have quotes and variables in the text easily as well:

example output
$ ./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

Solution 5 - Bash

read does not export the variable (which is a good thing most of the time). Here's an alternative which can be exported in one command, can preserve or discard linefeeds, and allows mixing of quoting-styles as needed. Works for bash and zsh.

oneLine=$(printf %s \
	a	\
	" b "	\
	$'\tc\t'	\
	'd '	\
)
multiLine=$(printf '%s\n' \
	a	\
	" b "	\
	$'\tc\t'	\
	'd '	\
)

I admit the need for quoting makes this ugly for SQL, but it answers the (more generally expressed) question in the title.

I use it like this

export LS_COLORS=$(printf %s	\
	':*rc=36:*.ini=36:*.inf=36:*.cfg=36:*~=33:*.bak=33:*$=33'	\
	...
	':bd=40;33;1:cd=40;33;1:or=1;31:mi=31:ex=00')

in a file sourced from both my .bashrc and .zshrc.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser2219963View Question on Stackoverflow
Solution 1 - BashNik O'LaiView Answer on Stackoverflow
Solution 2 - BashdogbaneView Answer on Stackoverflow
Solution 3 - BashislijepcevicView Answer on Stackoverflow
Solution 4 - BashBrad ParksView Answer on Stackoverflow
Solution 5 - BashEndlosSchleifeView Answer on Stackoverflow