Reputation: 59
I'm writing a function that'll accept 2 arguments - the name of a scalar and and a filename and will write the scalar (newline delimited) to that file. I'm getting a "bad substitution" error. Here's my code:
#!/bin/bash
arr_to_f() {
for y in "${1[@]}"
do
echo "$y" >> "$2"
done
}
mapfile -t arr < <(echo "one" ; echo "two" ; echo "three")
arr_to_f arr file
I could do it outside the function using my loop but ill be using this a lot i think so id rather be able to call it if possible.
Upvotes: 0
Views: 197
Reputation: 4698
You could create a named reference to your arr
variable. I also replaced echo
with printf
in your code, see Why is printf better than echo?.
#!/bin/bash
arr_to_f() {
local -n myarray=$1
for y in "${myarray[@]}"; do
printf '%s\n' "$y"
done >>"$2"
}
mapfile -t arr < <(printf '%s\n' one two three)
arr_to_f arr file
You could also get rid of the for-loop in your function:
arr_to_f() {
local -n myarray=$1
printf '%s\n' "${myarray[@]}" >>"$2"
}
Upvotes: 2
Reputation: 6979
NOTE: This answer uses eval
, and should be avoided where possible. See Freddy's answer, which uses declare -n
/ local -n
to create a named reference.
This approach may be necessary if you're using an old version of bash.
As already pointed out, you're passing the literal string arr
, and that isn't an array, hence the "bad substitution".
You can to use eval
to build a string that results in expanding to what you're after:
arr_to_file() {
local cmd
printf -v cmd 'local -a _content=( "${%q[@]}" )' "${1}"
eval "${cmd}"
printf '%s\n' "${_content[@]}" > "${2}"
}
mapfile -t arr < <(echo "one" ; echo "two" ; echo "three")
arr_to_file arr file
eval
usually gets a big warning notice, so here's yours: "eval is super dangerous if you don't trust the string you're giving it".
If we're very careful with eval
, then it can be used somewhat safely. Here printf "%q" "${1}"
is used to quote the first argument suitably for shell input (e.g: printf '%q' '}'
won't break out of the variable's name). Thanks to Charles Duffy for the revised and significantly safer and more readable snippet.
This approach will also work for associative arrays (i.e: arrays that use keys instead of indexes), but the output will be unordered.
Upvotes: 1