1

In Bash for macOS, I need to be able to pass a string to a function and return the value of a variable named after that string, as well as the string itself.
Here's what I have so far, which doesn't work:

varTest="If you can read this, it worked"

function testFunction {
    echo "Variable name is $1"
    echo "Contents are $(${$1})"
}

testFunction varTest
> Variable name is varTest
> Contents are varTest

When actually the second line should say Contents are If you can read this, it worked.
In PowerShell it'd be easy:

$varTest="If you can read this, it works"

function testEcho ($string) {
   write-host "Variable name is $string"
   (get-variable $string).value
}

testEcho varTest
> Variable name is varTest
> If you can read this, it works

Does bash have any equivalent to Get-Variable?
This will be for Bash (not ZSH) on macOS devices (so v3.2.57).

9
  • 2
    use the ref printf '%s\n' "${!1}"
    – Fravadona
    Commented Feb 3 at 16:33
  • That worked, thank you. If you set this as the answer I'll mark it as correct.
    – seagull
    Commented Feb 3 at 16:47
  • You're welcome. I can't post it as an answer as there's probably a lot of duplicates for this question.
    – Fravadona
    Commented Feb 3 at 16:52
  • Well, "come what may" to the question, then. I've got my answer and you have my thanks.
    – seagull
    Commented Feb 3 at 17:04
  • 2
    @eyoung100, are you sure that's the Q you meant to mark this as a duplicate of...?
    – ilkkachu
    Commented Feb 3 at 18:08

3 Answers 3

3

In pretty much all versions of Bash (including 3.2), you can use the ${!var} form of indirect expansion, which expands to the contents of the variable named in the variable $var. E.g.

foo=hello
p=foo
echo "${!p}"

prints hello.

In Bash 4.3 and later, you can also use namerefs, i.e. variables declared with typeset -n p=foo or declare -n p=foo. This also prints hello.

foo=hello
declare -n p=foo
echo "$p"

Namerefs also work in ksh, and have somewhat more useful behaviour when referring to arrays, i.e. indexing the nameref indexes the named array:

a=(zero one two)
typeset -n p=a
echo "${a[1]}"

prints one.

With ${!p} you need to put the index inside the indirectly expanded variable:

a=(zero one two)
p='a[1]'
echo "${!p}"

(${!p[1]} would treat p as an array, pick index 1 from it, and use the contents of that as the final variable to expand. The difference is similar to an array of pointers vs. a pointer to an array in something like C.)

In a lot of cases where one thinks of using indirect expansion, it's probably worth considering if associative arrays would be a better fit, see e.g. Bash's manual on Arrays or Does bash provide support for using pointers?

0

With bash 4.3+ you could use a nameref, eg:

function testFunction { 
    declare -n _var="$1"                    # '-n' == nameref
    echo "Variable name is ${!_var}"
    echo "Contents are ${_var}" 
}

NOTE: pick a variable name (_var in this case) that you're sure won't exist in the parent environment otherwise you'll end up with a runtime error related to a circular reference

Taking for a test drive:

$ varTest="If you can read this, it worked"
$ testFunction varTest
Variable name is varTest
Contents are If you can read this, it worked

$ othervar="something completely different"
$ testFunction othervar
Variable name is othervar
Contents are something completely different
1
  • 1
    MacOS doesn't support bash past 3.2.57 unless you download and install a version via Homebrew
    – eyoung100
    Commented Feb 3 at 17:21
-2

testFunction varTest

You are just passing the literal “varTest”. Try “$varTest”

1
  • This is my bad and I'll adjust my question accordingly. It's important that the string be passed and not the contents of its variable. I need to be able to say both varTest and what varTest redirects to. I'll now make my question clearer.
    – seagull
    Commented Feb 3 at 16:38

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.