Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to split a multi-line string containing the characters "\n" into an array of strings in bash? [duplicate]

I have a string in the following format:

I'm\nNed\nNederlander
I'm\nLucky\nDay
I'm\nDusty\nBottoms

I would like to move this to an array of strings line by line such that:

$ echo "${ARRAY[0]}"
I'm\nNed\nNederlander

$ echo "${ARRAY[1]}"
I'm\nLucky\nDay

$ echo "${ARRAY[2]}"
I'm\nDusty\nBottoms

However, I'm running into problems with the "\n" characters within the string itself. They are represented in the string as two separate characters, the backslash and the 'n', but when I try to do the array split they get interpreted as newlines. Thus typical string splitting with IFS does not work.

For example:

$ read -a ARRAY <<< "$STRING"
$ echo "${#ARRAY[@]}"   # print number of elements
2

$ echo "${ARRAY[0]}"
I'mnNednNederla

$ echo "${ARRAY[1]}"
der
like image 225
Cory Klein Avatar asked Jul 31 '12 17:07

Cory Klein


People also ask

How do I split a string over multiple lines?

You can have a string split across multiple lines by enclosing it in triple quotes. Alternatively, brackets can also be used to spread a string into different lines. Moreover, backslash works as a line continuation character in Python. You can use it to join text on separate lines and create a multiline string.

How do you split a string into multiple lines in Unix?

To split long commands into readable commands that span multiple lines, we need to use the backslash character (\). The backslash character instructs bash to read the commands that follow line by line until it encounters an EOL.


2 Answers

By default, the read builtin allows \ to escape characters. To turn off this behavior, use the -r option. It is not often you will find a case where you do not want to use -r.

string="I'm\nNed\nNederlander I'm\nLucky\nDay I'm\nDusty\nBottoms"  arr=() while read -r line; do    arr+=("$line") done <<< "$string" 

In order to do this in one-line (like you were attempting with read -a), actually requires mapfile in bash v4 or higher:

mapfile -t arr <<< "$string" 
like image 197
jordanm Avatar answered Sep 30 '22 10:09

jordanm


mapfile is more elegant, but it is possible to do this in one (ugly) line with read (useful if you're using a version of bash older than 4):

IFS=$'\n' read -d '' -r -a arr <<< "$string"
like image 37
chepner Avatar answered Sep 30 '22 08:09

chepner