3

I would like to combine default assignment, as seen here, with conversion to lowercase, as seen here.

This is what I'm working with:

bash-3.2$ export MY_ENV_VAR=FaLsE
bash-3.2$ : "${MY_ENV_VAR:=false}"
bash-3.2$ echo $MY_ENV_VAR
FaLsE

I would like to set the value of MY_ENV_VAR to lowercase in a single statement since I have 20+ lines of code grabbing values of environment variables and I'd rather not add 20+ additional lines to do the conversion by itself.

I've tried a few things, like:

bash-3.2$ : "${MY_ENV_VAR:=false,,}"
bash-3.2$ echo $MY_ENV_VAR
FaLsE

That method seems like it would work if I had Bash 4 but I'm on 3.2.

I've also tried:

bash-3.2$ myval=$(: "${MY_ENV_VAR:=false}" | tr '[:upper:]' '[:lower:]')
bash-3.2$ echo $myval

bash-3.2$

And:

bash-3.2$ myval=$(: echo "${MY_ENV_VAR:=false}" | tr '[:upper:]' '[:lower:]')
bash-3.2$ echo $myval

bash-3.2$

Which I didn't expect to work but I don't understand the default assignment enough to know how that would be used to feed the conversion to lowercase. I find certain features of Bash difficult to understand.

2
  • As simple as that with Bash: export MY_ENV_VAR=FaLsE; MY_ENV_VAR=${MY_ENV_VAR,,}; MY_ENV_VAR=${MY_ENV_VAR:=false} Commented Jun 29, 2022 at 14:56
  • Universal Bash function to export lowercased value or default. Arg1 is variable name to export, Arg2 is default value. exportLowerDefault() { v=${!1};v=${v,,};v=${v:=$2};export "$1=$v";} Commented Jun 29, 2022 at 15:28

4 Answers 4

3

Since you are using Bash, use built-in case modification:

#!/bin/bash

export MY_ENV_VAR=
for MY_ENV_VAR in FaLsE '' tRuE
do
  # Expands to lower-case
  MY_ENV_VAR=${MY_ENV_VAR,,}

  # Assigns default value
  MY_EN_VAR=${MY_ENV_VAR:=false}

  # Prints it to see
  printf 'MY_ENV_VAR=%s\n' "$MY_ENV_VAR"
done

Actual output is as expected:

MY_ENV_VAR=false
MY_ENV_VAR=false
MY_ENV_VAR=true

Now, rather than repeating this 20+ times for every variable, then make it into a function:

exportLowerDefault() {
  local -- v=${!1}
  v=${v,,}
  v=${v:=$2}
  export "$1"="$v"
}

for MY_ENV_VAR in FaLsE '' tRuE
do
  exportLowerDefault MY_ENV_VAR false

  # Prints it to see
  printf 'MY_ENV_VAR=%s\n' "$MY_ENV_VAR"
done
Sign up to request clarification or add additional context in comments.

1 Comment

this requires bash 4.0+. OP's using bash 3.2.
2

Unfortunately, you cannot use nested substitution in bash (and most other shells).

However, in your specific case you can use tools such a tr to handle the lowercase conversion, and use variable substitution to handle the default value.

For instance :

MY_ENV_VAR=$(tr [:upper:] [:lower:] <<< ${MY_ENV_VAR:=false})

Another (uglier) solution would be to use a subshell :

MY_ENV_VAR=$(TMP=${MY_ENV_VAR,,}; echo "${TMP:=false}")

2 Comments

This does not gain anything against sequential substitutions for lower-casing and assigning a default value. Spawning the sub-shell and pipeline may cost even more in the end, compared to sequential expansions.
@LéaGris quotting from the original question : I would like to set the value of MY_ENV_VAR to lowercase in a single statement since I have 20+ lines of code grabbing values of environment variables. For environment variables, the performance cost should be negligible compared to sequencial substitution
1

A function is an entity for encompassing a sequence of repeated tasks.

set_default_value_and_conver_to_lowercase() {
   declare -n _var=$1
   : "${_var:-$2}"
   _var=${_var,,}
}

set_default_value_and_conver_to_lowercase MY_ENV_VAR false

For that old bash3, you could use eval instead of namereference, hopefully with some error checking:

set_default_value_and_conver_to_lowercase() {
   local _var
   if ! <<<"$1" grep -qx '[A-Z_]*'; then exit 1; fi
   eval "_var=\${$1}"
   : "${_var:-$2}"
   _var=${_var,,}
   printf -v "$1" "%s" "$_var"
}

set_default_value_and_conver_to_lowercase MY_ENV_VAR false

1 Comment

+1 This answers the next question that came up while doing this and while I'd like to accept it as the answer, @Aserre's answer above is the most direct answer to this question.
0

This seems to work for me -

MY_ENV_VAR=$(tr [:upper:] [:lower:] <<< $MY_ENV_VAR)
echo $MY_ENV_VAR
# false

3 Comments

Don't use backticks, they are obsolete. You should prefer the $(...) syntax when using bash
Also, you solution doesn't handle the default value problem. tr [:upper:] [:lower:] <<< ${MY_ENV_VAR:=false} would though
@Aserre please submit as an answer. Your solution is what I'm after!

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.