相关文章推荐
玩足球的麻辣香锅  ·  输入awk '{print ...·  2 周前    · 
小眼睛的香菜  ·  /bin/bash -c "$(curl ...·  2 周前    · 
腼腆的沙发  ·  windows ...·  2 周前    · 
坚强的伤疤  ·  InvalidRequestError: ...·  8 月前    · 
喝醉的小笼包  ·  动态 线程池 ...·  11 月前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I would like to test if the name of a variable given as argument to a function contains a certain string, and do different actions if it does/does not.

Here is a very basic description of what I want to achieve:

#!/bin/bash
 varA="a"
 varB="b"
 varC="c"
 varD="d"
 varE="e"
 varF="f"
 function1 ()
         if name of argument $1 does not contain "A"; then
                echo "no A in $1"
                further actions done using the value of varA and others...
         elif name of argument $1 contains "A"; then
                echo "A in $1"
                further actions done using the value of varA and others...
 function1 $varA $varB $varC
 function1 $varD $varE $varF     

And when running this would give

A in varA
no A in varD

I saw while doing some research that the name of a variable could be referred to as ${!var@}, so here is the code I tried:

  1 #!/bin/bash
  3 varA="a"
  4 varB="b"
  5 varC="c"
  6 varD="d"
  7 varE="e"
  8 varF="f"
 10 function1 ()
 12         if [[ "${!1@}" != *"A" ]]; then
 13                 echo "no A in $1"
 14         elif [[ "${!1@}" == *"A" ]]; then
 15                 echo "A in $1"
 16         fi
 19 function1 $varA $varB $varC
 20 function1 $varD $varE $varF

But when running the script it gives the following error messages:

./testx.sh: line 12: ${!1@}: bad substitution
./testx.sh: line 12: ${!1@}: bad substitution

Any help would be much appreciated! Thank you

I don't think it's possible with positional arguments. When the function is called the variables are replaced with values already so there is no variable name to refer to. – karakfa Aug 24, 2016 at 15:54 The call is actually function1 $varA $varB $varC (see my second code), and I am not using the values of the variables here, but in the real script I am working on, I want to use their values to perform other actions in the function. – arielle Aug 24, 2016 at 16:44 @arielle: OK. In that case, It's not possible. Note that ${!prefix@} "Expands to the names of variables whose names begin with prefix"; that is, it is the equivalent to the file glob prefix*, but over the names of shell variables. prefix is just a string of characters. – rici Aug 24, 2016 at 16:48 I see. Then why can't I use ${!@}? Shouldn't this expand to the names of all arguments, something like varA varB varC or $varA $varB $varC? Both would be good for what I want to do. When I try it it gives some empty lines as output. – arielle Aug 24, 2016 at 16:52 @arielle: {!@} is not valid, but if it were valid it would be the list of all variables. An argument is just a string; arguments don't have names. (More precisely, they do have names: $1, $2, ...., but those are parameter names, not variable names. The expression which produced the argument is not its name.) The reason you can't do what you want to do is that the argument has already undergone parameter expansion by the time your function sees it, so it is just a string (which is the value of the variable). – rici Aug 24, 2016 at 16:56

If you want to "test if the name of a variable" then give that to the function:

function1 varA

Not the contents of the variable:

function1 $varA             # INCORRECT

Then, you could test the name of the variable inside the function:

if [[ $1 == *A* ]]; then

The script could be as this one:

#!/bin/bash
function1 ()
        if [[ $1 == *A* ]]; then
               echo "A in $1"
               echo "no A in $1"
function1 varA varB varC
function1 varD varE varF

IF you need "the value of the var" inside the function, then just use this:

value=${!1}

That is called "indirect expansion" inside the man bash.

After that, value will contain a copy of the variable named in $1.

To change the value of the variable pointed by $1, use this:

declare $1=newvalue

Or, quite insecure if the value of $1 could be set by an external user:

eval $1=newvalue

The use of ${!var*} (or ${!var@}) is to get a list of all variables that use a name that start with var. Not to reference a particular variable.

$ eval var{A..F}=1               # create the list of variables
$ echo ${!var*}                  # use the expansion to list variables
varA varB varC varD varE varF

The expansion of ${!1*} should have been the list of variables that start with a 1. Those variable names are invalid (except as positional parameters) in bash. That is: variable names could not start with a number.

That expansion is (therefore) an error, and reported as so by bash.

but in my real script I want to use the value of the first argument to do more actions inside the function, not just its name, would it still work? – arielle Aug 24, 2016 at 15:56 I did not know "${!var*}" syntax to find all the defined variables starting with var. Thanks! – anishsane Aug 24, 2016 at 16:14 @anishsane : in fact I came to know about it a couple of months ago when skimming through [ this ] page. This was adopted from ksh IIRC and it first appeared in bash version 2.04 . – sjsam Aug 24, 2016 at 16:17

Be aware the script you are looking for checks only for the first variable of the function call (i.e. $1). So calling for function1 $varA $varB $varC would only check for varA

The code below would do the work you expect under the pseudo code you have written:

#!/bin/bash
varA="checkAinvariable"
varB="b"
varC="c"
varD="d"
varE="e"
varF="f"
function1 ()
        if [[ "$1" != *"A"* ]]; then
                echo "no A in $1"
        elif [[ "$1" == *"A"* ]]; then
                echo "A in $1"
function1 $varA $varB $varC
function1 $varD $varE $varF

Output would be:

A in checkAinvariable
no A in d
                The op said name of a variable given as argument to a function contains a certain string. It's name not the value pal !
– sjsam
                Aug 24, 2016 at 16:09
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.