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

39,138

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"
Share:
39,138
Cory Klein
Author by

Cory Klein

Computer science enthusiast, open source advocate, frugality expert

Updated on July 15, 2022

Comments

  • Cory Klein
    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
    Vic Seedoubleyew about 8 years
    Indeed, and -d option seems crucial to make it work
  • chepner
    chepner almost 8 years
    One 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
    electronix384128 almost 7 years
    yeah for mapfile oneliner :)