AlexH
AlexH

Reputation: 59

how can i add to a file from a scalar in bash?

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

Answers (2)

Freddy
Freddy

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

Attie
Attie

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

Related Questions