Bash functions returning values meanwhile altering global variables

I'm just struggling with bash functions, and trying to return string values meanwhile some global variable is modified inside the function. An example:

MyGlobal="some value"

function ReturnAndAlter () {
  MyGlobal="changed global value"
  echo "Returned string"
}

str=$(ReturnAndAlter)
echo $str            # prints out 'Returned value' as expected
echo $MyGlobal       # prints out the initial value, not changed

This is because $(...) (and also `...` if used instead) cause the function to have its own environment, so the global variable is never affected.

I found a very dirty workaround by returning the value into another global variable and calling the function only using its name, but think that there should be a cleaner way to do it.

My dirty solution:

MyGlobal="some value"
ret_val=""

function ReturnAndAlter () {
  ret_val="Returned string"
  MyGlobal="changed value"
}

ReturnAndAlter            # call the bare function
str=$ret_val              # and assign using the auxiliary global ret_val 
echo $str
echo $MyGlobal            # Here both global variables are updated.

Any new ideas? Some way of calling functions that I'm missing?

Upvotes: 0

Views: 472

Answers (2)

chepner
chepner

Reputation: 532418

Setting global variables is the only way a function has of communicating directly with the shell that calls it. The practice of "returning" a value by capturing the standard output is a bit of a hack necessitated by the shell's semantics, which are geared towards making it easy to call other programs, not making it easy to do things in the shell itself.

So, don't worry; no, you aren't missing any cool tricks. You're doing what the shell allows you to do.

Upvotes: 1

user8017719
user8017719

Reputation:

The $(…) (command expansion) is run in a sub-shell.
All changes inside the sub-shell are lost when the sub-shell close.

It is usually a bad idea to use both printing a result and changing a variable inside a function. Either make all variables or just use one printed string.

There is no other solution.

Upvotes: 0

Related Questions