neckutrek
neckutrek

Reputation: 353

BASH: How to echo output from function that edits global variable

In general, how do one echo the output from a function while that function is editing a global variable? What's the best practice here?

I've tried calling the function in a subshell as an argument to echo. But then the global variable is not edited for the parent environment.

declare -a ARR
f () {
  ARR+=("$1")
  echo "added $1"
}
echo $(f a)
f b
f c
echo "${ARR[@]}"

I expect the output:

added a
added b
added c
a b c

But I'm getting

added a
added b
added c
b c

Upvotes: 1

Views: 373

Answers (1)

KamilCuk
KamilCuk

Reputation: 142005

how do one echo the output from a function while that function is editing a global variable?

You can use a temporary file:

tmp=$(mktemp)
f > "$tmp"
output="$(<"$tmp")"
rm "$output"
echo "$output"

What's the best practice here?

This is subjective and opinion based. Don't grab the output of a function. If you have a function that modifies global state, why not pass the output using some global variable, too?

f() {
   declare -g -a ARR
   ARR+=("$1")
   declare -g f_log
   f_log+="added $1"
}
f
echo "$f_log"

Leave the stdout of a function for some logging and error reporting. There is no reason to grab the function output, it's already a function, it can modify the state of the program in any way.

Side note:

I recently tried to interleave stdout of a function for data and output and I did this:

f() {
    source /dev/stdin <<<"$1"
    shift 1
    ARR+=("$1")
    declare -p ARR
    echo
    echo "added $1"
}
tmp=$(f "$(declare -p ARR)" a)
source /dev/stdin < <(<<<"$tmp" sed -n '0,/^$/p')
echo "$(<<<"$tmp" sed '0,/^$/d')"

which actually adds more hassle then it's worth.

Upvotes: 1

Related Questions