How to split a multi-line string containing the characters "\n" into an array of strings in bash?
Solution 1
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"
Solution 2
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"
Cory Klein
Computer science enthusiast, open source advocate, frugality expert
Updated on July 15, 2022Comments
-
Cory Klein almost 2 years
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
-
Vic Seedoubleyew about 8 yearsIndeed, and -d option seems crucial to make it work
-
chepner almost 8 yearsOne caveat I did not know about when I posted this: the exit status will be non-zero, since a here string will never end with a null character like
read -d ''
will expect. -
electronix384128 almost 7 yearsyeah for mapfile oneliner :)