Dan-Simon Myrland
Dan-Simon Myrland

Reputation: 337

Bash indirect variable assignment inside a function

I have a script where the user input needs to be evaluated several times, the solution im working on is to put the evaluation bits into a function, and simply call the function every time i need to evaluate the input. The problem is though that when im trying to update the $1 variable (that referes to the first variable parameter of the function) I get the error message "$VARIABLE command not found".

Here is the code:

function input_handler() {
 if is_integer $1; then
  selid="$1 -1"
  if [[ "$1" -le "0" ]]; then
   echo "Please use a simple positive number!"
  else
   if [[ "$1" -le "${#array[*]}" ]]; then
    eval $1="${array[selid]}"
    echo "Ok, moving on..."
   else
    echo "That number seems too large, try again?"
   fi
  fi
 else
  if [ -e $2/$1 ]; then
   echo "Ok, moving on..."
  else
   echo "That item is not on the list, try again!"
  fi
 fi
}

And this command:

input_handler $doctype $docpath

Gives this output:

5
./test: line 38: 5=sun: command not found

Ok, moving on...

Now this is almost correct, but what im after is doctype=sun, not 5=sun, in other words I need the $1 variable name not its value. Changing the line eval $1="${array[selid]}" to eval doctype="${array[selid]}" fixes this particular instance. But this does not fix my problem as I need to run this function on different variables with different names.

Upvotes: 5

Views: 3275

Answers (4)

clt60
clt60

Reputation: 63902

Maybe not fully understand what you want achieve, but check the next example:

weirdfunc () {
    echo " weirdfunc: variable name is: $1"
    echo " weirdfunc: variable value is: ${!1}"
    eval "$1=$(( ${!1} + 1))" #assign
}

myvar="5"
echo "the value of myvar before: $myvar"

weirdfunc myvar #call with the NAME not with the value, so NOT weridfunc $myvar

echo "the value of myvar after: $myvar"

In short - when you want to do anything with the variable NAME in an called function, you should pass the NAME of the variable and NOT his value. So call the function

somefunc NAME

instead of

somefunc $NAME

and use the above constructs to get the name and value inside the function.

Upvotes: 4

Joao Morais
Joao Morais

Reputation: 1925

If you protect the variable name, Bash will evaluate and assign to $1 instead of try to execute $1=value.

eval "$1"=${array[selid]}

Upvotes: 0

kojiro
kojiro

Reputation: 77089

You can't update the value of $1 with a traditional assignment, but you can update the positional parameters with the set builtin.

$ f() { echo "$@"; set -- a b c; echo "$@"; echo $2; }
$ f 1 2 3
1 2 3
a b c
b

Just keep in mind this will wipe out all the positional parameters you don't re-set each time, so you'll need to set $2 if you want to keep it around.

Your best bet is probably to assign the values in the positional parameters to names and just use names from then on.

Upvotes: 0

user123444555621
user123444555621

Reputation: 152966

Positional parameters are read-only. So what you want to do is not possible. You should do something like

foo=$1

and then work with $foo instead of $1

Upvotes: -1

Related Questions