Reputation: 767
I have a string
echo $STRING
which gives
first second third fourth fifth
basically a list separated spaces.
how do i take that string and make it an array so that
array[0] = first
array[1] = second
etc..
I have tried
IFS=' ' read -a list <<< $STRING
but then when i do an
echo ${list[@]}
it only prints out "first" and nothing else
Upvotes: 15
Views: 22297
Reputation: 295619
Your original code generally works -- the quoting is a bit off (and how much that matters is version-specific: you wouldn't see your original bug on a newer version of bash), but nothing further.
After:
# assign string
string='this is several words'
# split string to a list
IFS=' ' read -r -a list <<<"$string"
...you can run:
# print a definition of the variable list
$ declare -p list
declare -a list=([0]="this" [1]="is" [2]="several" [3]="words")
# print each item in the list array on a separate line
$ printf ' - %s\n' "${list[@]}"
- this
- is
- several
- words
# still works with echo; change IFS to show that we're really an array
$ IFS=':' echo "${list[*]}"
this:is:several:words
More importantly, it also works in cases where the competing answer doesn't:
# need to be in a non-empty directory to demonstrate
$ touch a.txt b.txt c.txt
# put literal asterisks as separate words in our string
$ string='list * contains * asterisks'
# reading those using read -a works fine
$ IFS=' ' read -r -a list <<<"$string"
# whereas the array=( $string ) is NOT fine
$ IFS=' '; buggyList=( $string )
# print both arrays' contents
$ declare -p list buggyList
declare -a list=([0]="list" [1]="*" [2]="contains" [3]="*" [4]="asterisks")
declare -a buggyList=([0]="list" [1]="a.txt" [2]="b.txt" [3]="c.txt" [4]="contains" [5]="a.txt" [6]="b.txt" [7]="c.txt" [8]="asterisks")
As you can see, the list=( $string )
answer gets filenames injected into its contents, but the read -a
list contains exactly the word-split contents of your original string.
Upvotes: 0
Reputation: 839
It's simple actually:
list=( $STRING )
Or more verbosely:
declare -a list=( $STRING )
PS: You can't export IFS and use the new value in the same command. You have to declare it first, then use its effects in the following command:
$ list=( first second third )
$ IFS=":" echo "${list[*]}"
first second third
$ IFS=":" ; echo "${list[*]}"
first:second:third
Notice that the last example will change IFS
to ":"
until you change it again, or the shell exits.
Usually you want to use a subshell, or save the original value of IFS
so you can restore it afterwards.
Upvotes: 27