0

I'm checking whether or not environment variables are set.

This gives me exactly what I want in the singular:

 : ${API_KEY:?`echo "Need to set API_KEY"`}

However, when I extract a function to loop over a collection of variables, things don't work like I'd expect.

 function check_env_for { 
   : ${$1:?`echo "Need to set $1 non-empty"`}
 }
 check_env_for API_KEY

breaks, returning:

 -bash: ${$1:?`echo "Need to set $1 non-empty"`}: bad substitution

While a solution is appreciated, what core shell fundamentals am I likely missing?

3 Answers 3

1

Along the lines of what you are trying, you can use indirect parameter expansion. This does require a temporary variable, which shouldn't be much of a hardship as this is a function definition:

function check_env_for {
    local foo="$1"
    : ${!foo:?"Need to set $foo non-empty"}
}

However, note that the error message isn't ideal:

$ check_env_for FOO
bash: !foo: Need to set FOO non-empty

Since you are writing a function, it's probably clearer to skip the "Display Error" parameter expansion and just test for a non-empty string, again using indirect parameter expansion:

check_env_for () {
    [[ -z ${!1} ]] && printf "Need to set $1 non-empty\n"
}
Sign up to request clarification or add additional context in comments.

2 Comments

This produces an error locally. check_env_for:1: bad substitution
Are you sure you are using bash? Works for me in 3.2.51
0

I got it working with the following code, which you can modify to suit your needs:

function check_env_for { 
   KEY="$(eval echo \$$1)"
   echo ${KEY:-"Need to set $1 non-empty"}
}
check_env_for API_KEY

Here it is in one line:

function check_env_for { 
  echo ${$(eval echo \$$1):-"Need to set $1 non-empty"}
}

This returns either the value of $API_KEY or Need to set API_KEY non-empty

5 Comments

This doesn't echo anything, whether or not the parameter exists as a variable.
Don't use eval to re-implement indirect parameter expansion.
The eval is necessary to obtain the value of the the ENV variable in this context. This is what eval is for.
If you are using bash, eval is not necessary. Using eval is never a good idea, since it will evaluate whatever is in the expanded variable, not just what you assume the contents will be.
eval was created for just such purposes. Yes, I agree it's not always the best solution, particularly if you don't control your environment, but in this case, based upon the OP, I think it's the right solution. Sometimes simple is best.
0

Using ${parameter:?word} expansion does the trick but the output looks unpleasant. Using ${parameter:-word} expansion does look better.

If you still prefer the former, your code should look like this.

#!/bin/bash
function check_env_for {
        eval : \${$1:?"Need to set $1 non-empty"}
}
check_env_for API_KEY

Give this one a try and see if you like it.

#!/bin/bash
function check_env_for {
        eval echo \${$1:-"Need to set $1 non-empty"}
}
check_env_for API_KEY

The eval in both code will evaluate $1 and expand it to API_KEY. The $ outside of {} is escaped therefore it will not be expanded on eval.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.