How do i convert a string like this in BASH to an array in bash!
I have a string str which contains "title1 title2 title3 title4 title5" (space seperated titles)
I want the str to modified to an array which will store each title in each index.
How do i convert a string like this in BASH to an array in bash!
I have a string str which contains "title1 title2 title3 title4 title5" (space seperated titles)
I want the str to modified to an array which will store each title in each index.
In order to convert the string to an array, say:
$ str="title1 title2 title3 title4 title5"
$ arr=( $str )
The shell would perform word splitting on spaces unless you quote the string.
In order to loop over the elements in the thus created array:
$ for i in "${arr[@]}"; do echo $i; done
title1
title2
title3
title4
title5
I am in an unfortunate position where I have a long-standing shell script that is upgrading from internally using scalar variables to using arrays. But, users are also allowed to set those variables themselves, optionally, with a file that is sourced on startup.
So, I needed to make a way to conditionally convert a scalar to an array, depending on whether the user's sourced script is declared in the new way or the old way.
My solution is overkill for the simple case above, but I wanted to document it for others looking for this solution, because it was non-trivial coming up with something that handled my use case.
The only way I've come up with to reliably handle all options safely is thus:
convert_array() {
__array_name="$1"; shift
__declaration="$(declare -p "$__array_name" 2>/dev/null)"
if [ -z "${__declaration}" ]; then
# variable is not set
eval "${__array_name}=()"
elif [ "$(echo "${__declaration}" | grep -c '^declare \-a')" -eq 0 ]; then
# variable is not an array
__existing_value="$(eval echo "\${$__array_name}" | sed -e 's,^[[:space:]]*,,' -e 's,[[:space:]]*$,,')"
unset "${__array_name?}"
IFS=" " read -r -a "${__array_name?}" <<< "${__existing_value}"
fi
}
It cleanly handles all cases: existing variable, existing array, and not set at all.
Also note that while this may seem like overkill:
__existing_value="$(eval echo "\${$__array_name}" | sed -e 's,^[[:space:]]*,,' -e 's,[[:space:]]*$,,')"
...it handles the case that most people are building their sourced configurations something like this:
ADDITIONAL_OPTIONS="${ADDITIONAL_OPTIONS} -Xmx2g"
ADDITIONAL_OPTIONS="${ADDITIONAL_OPTIONS} -Dsome.property=foo"
In these cases, the $ADDITIONAL_OPTIONS
variable will start with a space. If you know your inputs won't need trimming, that bit is unnecessary.
test_foo() {
convert_array FOO
for VAR in "${FOO[@]}"; do
echo "var=$VAR"
done
}
$ FOO="foo bar baz"
$ test_foo
var=foo
var=bar
var=baz
$ unset FOO
$ test_foo
$ FOO=(foo bar baz "something with spaces")
$ test_foo
var=foo
var=bar
var=baz
var=something with spaces