I have a multiline string and I want to split is based on \n
for which I'm setting IFS=$'\n'
but it's not working, I've also tried IFS=
and IFS="
"
but no luck.
Below is the sample code
IFS=$'\n' read -ra arr <<< "line1\nline2\nline3"
printf "%s\n" "${arr[@]}"
# it only generates array of length 1
I'm using Ubuntu
with bash version being
GNU bash, version 4.4.19(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
<http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Can someone point out the obvious.
The primary problem with your attempt is word-splitting is not preformed with a herestring. From man bash:
Here Strings A variant of here documents, the format is: <<<word ... Pathname expansion and word splitting are not performed. The result is supplied as a single string to the command on its standard input.
Bash does provide a heredoc (e.g. "Here Document" in man bash) on which word-splitting will be preformed with the default IFS
. However, even then you will still read the literal '\n'
as part of the contents of the array. Not to fear, bash has provided a specific manner in which this can be avoided with the -t
option to readarray
(a/k/a mapfile
).
A short example as close as I can get to your original attempt would be:
readarray -t arr << EOF
line1
line2
line3
EOF
declare -p arr
Which results in your lines being saved as desired, e.g. the output would be:
declare -a arr='([0]="line1" [1]="line2" [2]="line3")'
The other alternative is to use process substitution and let printf
provide the splitting, e.g.
readarray -t arr < <(printf "line1\nline2\nline3\n")
The key to filling the array without the newlines included is readarray -t
, the key to allowing word-splitting to occur is to avoid the herestring.