Reputation: 53
In a bash script, I would like to transform a string containing variable separated by ":" into an array.
I see that the proposed approach is usually
IFS=: read -r -a myarray <<< "$mystring"
I used instead a command that looks simpler to me:
IFS=: myarray=($mystring)
Moreover on my PC it works. See the script hereunder
#!/bin/bash
mystring="var01:var02:var03:var04"
IFS=: myarray=($mystring)
echo "first variable is" "${myarray[0]}"
echo "second variable is" "${myarray[1]}"
echo "..."
output is
first variable is var01
second variable is var02
...
However, as I did not found such example on the web, I'm not sure it's correct...
What would be the issue of using this in bash script ? Is it compliant with standard ?
Thanks for your advice.
Upvotes: 4
Views: 52
Reputation: 4004
Nice first question. Your proposed alternative does have issues. First consider
$ str='a:%:*'
$ IFS=: read -r -a arr <<< "$str"
$ echo "${arr[@]}"
a % *
The result is the expected one. Because "$str"
is quoted in a herestring, it does not undergo filename expansion (as known as globbing) and all is quite right.
On the other hand...
$ str='a:%:*'
$ IFS=: arr=($str)
$ echo "${arr[@]}"
a % 07-13:37:38.png 07-13:37:49.png Documents Downloads Pictures Music Xresources
In this second case, $str
is unquoted and undergoes filename expansion, which means *
is expanded to all files in my current directory! Alas!
None of those forms are POSIX compliant because POSIX does not define arrays in shells. But both are totally valid in Bash, although, as demonstrated, they do different things.
A reference in Bash's manual: Filename Expansion.
As you have noted, you can use set -f
to disable filename expansion. That would solve the problem of IFS=: arr=($str)
, but may surprise some. If going this way, set it back with set +f
right after that line or the setting will apply to the whole rest of the script. It increases the complexity of the solution, so I recommend avoiding this whenever possible.
Upvotes: 6