简体   繁体   中英

Name of variable passed to function in bash

Is there a way in bash to understand the name of a variable that's passed to it?

Example:

var1=file1.txt
err_var=errorfile.txt

function func1 {
   echo "func1: name of the variable is: " $1
   echo "func1: value of variable is: " $1 
   echo
   if [ ! -e $var1 ]
   then
      $1 = $err_val  #is this even possible?
   fi
   func2 $1
}

function func2 {
   echo "func2: name of the variable is: " $1
   echo "func2: value of variable is: " $1 
   echo
}

func1 $var1
func1 $err_var

I was hoping to get the following output if file1.txt exists:

func1: name of the variable is: var1
func1: value of variable is: file1.txt

func2: name of the variable is: var1
func2: value of variable is: file1.txt

And when file1.txt does not exist:

func1: name of the variable is: var1
func1: value of variable is: file1.txt

func2: name of the variable is: err_var
func2: value of variable is: errorfile.txt

Any ideas?

No, the variable is expanded before the function sees it. The function only sees the value, not the variable name.

If you pass the variable name unexpanded and without the dollar sign, you can use indirection.

get_it () {
    echo "${!1}"
}

Demo:

$ foo=bar
$ baz=qux
$ get_it foo
bar
$ get_it baz
qux

Like Dennis said, once you've expanded the variable using the dollar-sign, your function no longer has a way to get the variable name. But I think you also asked about a way to set the variable's value, and that part hasn't been answered yet. There are some non-portable ways to do that, like with declare -n (Google that if you're interested), but my answer is going to stick to a universal solution.

I'm a C++ programmer, so I like to mimic the " getter and setter " philosophy, where you use tiny little functions to get and set the value of a variable. The downside to using getters and setters is that you need to create a function (or two functions) for every value you want to manage. So... I made a "factory function" that handles creating getters/setters for you:

makeGetSet() {
. /dev/fd/0 <<END_FUNC
${1}Val()  { [ "\${1}" ] && ${1}="\${1}" || echo "\${${1}}"; }
END_FUNC
}

It does not require any particular shell with special features like indirection or namerefs , or the declare utility. No eval , no alias es, just 100% POSIX. You just pass in your variable name to makeGetSet , and your getter/setter function has that same name with a " Val " at the end (eg myVariableVal ). Tested with bash and dash . You're free to continue using the "normal" shell ways to read/write to your variable in combination with my function.

Usage:

Setup: makeGetSet myVariable
Set: myVariableVal newValue
Get: anotherVariable="`myVariableVal`"
Print: myVariableVal

I wasn't sure about a couple parts of your script, so I took some educated guesses. Where you have if [ ! -e $var1 ] if [ ! -e $var1 ] , I think you meant if [ ! -e $1 ] if [ ! -e $1 ] . And at the end, where you call the functions, you had func1 $var1 and func1 $err_var , but I think you meant to just use func1 $var1 or have a third variable. It looks like $err_var is a "default value for errors" rather than something you'd give as input, but maybe I'm not following your idea.

So my answer to your question would look like:

var1=file1.txt; makeGetSet var1
err_var=errorfile.txt; makeGetSet err_var

function func1 {
   echo "func1: name of the variable is: " ${1%Val}
   echo "func1: value of variable is: " `${1}`
   echo
   # Shorter than if..fi
   [ ! -e `${1}` ] && ${1} ${err_val}
   func2 ${1}
}

function func2 {
   echo "func2: name of the variable is: " ${1%Val}
   echo "func2: value of variable is: " `${1}` 
   echo
}

func1 ${var1}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM