I am working towards writing a bash script that contains a variable with a long string value. When I split the string into multiple lines it is throwing error. How to split the string into multiple lines and assigned to a variable?
- 
        2Can you provide the data in your script and add it your question?Nasir Riley– Nasir Riley2019-02-28 15:28:38 +00:00Commented Feb 28, 2019 at 15:28
- 
        1What operation does the script perform on the variable? How are you splitting it? What is the error exactly?steeldriver– steeldriver2019-02-28 15:33:37 +00:00Commented Feb 28, 2019 at 15:33
- 
        I am assigning an SQL script to that variable and thereafter running the psql command to execute the SQL script on postgresql database. The SQL script which is assigned to the variable contains around 50 t0 75 lines.Srinivas Kamalanathan Attipatt– Srinivas Kamalanathan Attipatt2019-02-28 16:28:44 +00:00Commented Feb 28, 2019 at 16:28
- 
        1@SrinivasKamalanathanAttipatt please show - don't tell. In particular, things like how you are assigning values and whether you are properly quoting the string expansion may affect the answer. You can use the edit button to revise your question.steeldriver– steeldriver2019-02-28 17:11:44 +00:00Commented Feb 28, 2019 at 17:11
5 Answers
One suggestion:
x='Lorem ipsum dolor sit amet, consectetur '\
'adipiscing elit, sed do eiusmod tempor '\
'incididunt ut labore et dolore magna aliqua.'
Which results in the expected:
$ printf '%s\n' "$x"
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Assigning long strings as multiple sub-string in an array could make the code more aesthetically appealing:
#!/bin/bash
text=(
    'Contrary to popular'
    'belief, Lorem Ipsum'
    'is not simply'
    'random text. It has'
    'roots in a piece'
    'of classical Latin'
    'literature from 45'
    'BC, making it over'
    '2000 years old.'
)
# output one line per string in the array:
printf '%s\n' "${text[@]}"
# output all strings on a single line, delimited by space (first
# character of $IFS), and let "fmt" format it to 45 characters per line
printf '%s\n' "${text[*]}" | fmt -w 45
To do the opposite, i.e. to take a long line, split it into multiple lines, and read these into an array variable:
$ cat file
Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old.
We use fmt here to break the line down into shorter lines that are at most 30 characters long, then readarray in the bash shell to read these lines into the array called text:
$ readarray -t text < <(fmt -w 30 file)
Now we may access the set of lines, or each individual line:
$ printf '%s\n' "${text[@]}"
Contrary to popular belief,
Lorem Ipsum is not simply
random text. It has roots in a
piece of classical Latin
literature from 45 BC, making
it over 2000 years old.
$ printf '%s\n' "${text[3]}"
piece of classical Latin
(Note that arrays are zero-based in bash.)
If the point is to store a very long line in a shell variable, but for the code to do so not to exceed some fixed width, assuming a Bourne-like shell, you can do:
string="Rerum inventore nemo neque reiciendis ullam. Volupta\
te amet eveniet corporis nostrum. Laboriosam id sapiente atq\
ue non excepturi. Dolorem alias sed et voluptatem est unde s\
ed atque. Itaque ut molestias alias dolor eos doloremque exp\
licabo. Quas dolorum sint sit dicta nemo qui."
Inside double quotes (contrary to single quotes), backslash-newline is still treated as a line continuation). Beware that inside double quotes, ", $, `, \ (and sometimes !) are still special and would need to be escaped.
On approach that avoids having to worry about quoting is to write:
string=$(<<'EOF' tr -d '\n'
Rerum inventore nemo neque reiciendis ullam. Vo
luptate amet eveniet corporis nostrum. Laborios
am id sapiente atque non excepturi. Dolorem ali
as sed et voluptatem est unde sed atque. Itaque
 ut molestias alias dolor eos doloremque explic
abo. Quas dolorum sint sit dicta nemo qui. 'And
'#\`"$% whatever.
EOF
)
When the << delimiter is quoted, even partly, no expansion is made in the body of the here-document. Here, we capture the output of tr which is fed the here-document from which it deletes the newline characters. You could use a similar approach to add some indentation with:
string=$(<<'EOF' cut -b3- | tr -d '\n'
  Rerum inventore nemo neque reiciendis ullam. Vo
  luptate amet eveniet corporis nostrum. Laborios
  am id sapiente atque non excepturi. Dolorem ali
  as sed et voluptatem est unde sed atque. Itaque
   ut molestias alias dolor eos doloremque explic
  abo. Quas dolorum sint sit dicta nemo qui. 'And
  '#\`"$% whatever.
EOF
)
Assuming you want to assign the string some long piece of text to assign to the variable str. This won't work:
str='some long'
'piece of text'
'to assign'
It'll try to run the lines after the first as commands, you'll probably get "command not found" errors.
You can do this, but the newlines will be embedded in the variable, so it won't be a single line:
str='some long
piece of text
to assign'
Though you can use the substring replacement expansion (in Bash, ksh, zsh) to replace them with spaces, e.g. str="${str//$'\n'/ }" to do the replacement and save the new value in the same variable. Note that any trailing whitespace on all but the last line will be left in the string.
Another option is to use += to append to the value of the variable (also Bash, ksh, zsh only):
str='some long'
str+=' piece of text'
str+=' to assign'
Here, any whitespace will need to be manually typed within the quotes.
Or, similarly in a standard shell:
str='some long'
str="$str"' piece of text'
str="$str"' to assign'
Then there's the way with line continuation (that Jeff already mentioned in their answer):
str='some long'\
' piece of text'\
' to assign'
Here, too, trailing whitespace is important, the line continuation only works if the backslash is immediately followed by a newline, not if there are spaces in between.
- 
        Suppose I want to do this, but also maintain my nesting and indentation ?Amit Naidu– Amit Naidu2019-07-11 00:06:59 +00:00Commented Jul 11, 2019 at 0:06
- 
        @AmitNaidu, what nesting an indentation? There's no such mentioned in this question, and without a better description, there's no way to know what exactly you're doing. Please post a new question if you have a new question.ilkkachu– ilkkachu2019-07-11 07:10:01 +00:00Commented Jul 11, 2019 at 7:10
I would write it this way in a command line prompt. It could be, of course, more compressed, but for clarity’s sake:
~$ text='You can do this, but the newlines will be embedded in the variable, so it won’t be a single line'
~$ array=$(echo $text | cut -d' ' -f 1-)
~$ for x in ${array[@]}; do echo $x ; done
Here is a one liner:
~$ echo $text | tr ' ' '\n'
Output:
You
can
do
this,
but
the
newlines
will
be
embedded
in
the
variable,
so
it
won’t
be
a
single
line
Or, for a sorted output:
~$ echo $text | tr ' ' '\n' | sort
Output:
a
be
be
but
can
do
embedded
in
it
line
newlines
single
so
the
the
this,
variable,
will
won’t
You
- 
        please use proper syntaxmattia.b89– mattia.b892020-10-03 09:29:30 +00:00Commented Oct 3, 2020 at 9:29




