Loop Through Variables in bash and change their content

Viewed 22

How can I make this into a loop? I have trouble with looping through variables.

WSTATUS="exited" //example output from command
VSTATUS="running"
NSTATUS="running"
JSTATUS="running"


if [[ $WSTATUS == run* ]]; then
    WSTATUS=${GREEN}$WSTATUS
else
    WSTATUS=${RED}$WSTATUS
fi


if [[ $VSTATUS == run* ]]; then
    VSTATUS=${GREEN}$VSTATUS
else
    VSTATUS=${RED}$VSTATUS
fi


if [[ $NSTATUS == run* ]]; then
    NSTATUS=${GREEN}$NSTATUS
else
    NSTATUS=${RED}$NSTATUS
fi


if [[ $JSTATUS == run* ]]; then
    JSTATUS=${GREEN}$JSTATUS
else
    JSTATUS=${RED}$JSTATUS
fi

I have tried this:

...varibles

array=( $WSTATUS $VSTATUS $NSTATUS $JSTATUS )

for value in "${array[@]}"
do
    if [[ $value == run* ]]; then
        WSTATUS=${GREEN}$value
    else
        WSTATUS=${RED}$value
    fi
done

How can i iterate through bash variables, not their content? changing this wstatus into value does not work --> WSTATUS=${GREEN}$value

3 Answers

Not a loop, but a function already helps a lot:

colorme() {
  if [[ "$1" == run* ]]; then
    printf '%s' "${GREEN}$1"
  else
    printf '%s' "${RED}$1"
  fi
}

WSTATUS=$(colorme "$WSTATUS")
VSTATUS=$(colorme "$VSTATUS")
NSTATUS=$(colorme "$NSTATUS")
JSTATUS=$(colorme "$JSTATUS")

You can use nameref (declare -n var in following script)

#!/usr/bin/env bash

GREEN=GREEN
RED=RED

WSTATUS="exited"
VSTATUS="running"
NSTATUS="running"
JSTATUS="running"

array=( WSTATUS VSTATUS NSTATUS JSTATUS )
declare -n var

for var in "${array[@]}"
do
    [[ $var == run* ]] && prefix="${GREEN}" || prefix="${RED}"
    var="$prefix$var"
done

declare -p WSTATUS VSTATUS NSTATUS JSTATUS

What you are looking for is declare and ! expansion

a=b
declare $b=12
echo $b

=> 12

That is for setting a variable whose name is computed (here from another variable)

echo ${!a}

=> 12 That is for accessing the content of a variable whose name is stored in another variable

So in your case, it may look like

WSTATUS="exited" //example output from command
VSTATUS="running"
NSTATUS="running"
JSTATUS="running"

totest=( WSTATUS VSTATUS NSTATUS JSTATUS )

for name in ${array[@]}
do
    if [[ ${!name} == run* ]]; then
       declare $name=${GREEN}${!name}
    else
       declare $name=${RED}${!name}
    fi
done

Copying without any other modification your script. I have some reservation about the idea to add those, apparently green and red escape code to the variable content, rather than taking this decision at print time. I didn't really try do understand nor the test neither the action your script is taking. Even, (XY problem parenthesis) the fact that what you need is to loop through variable is questionable. knittl solution, tho it does not answer to your question, is probably a better solution to your real problem.

But well, your question was how to loop through variable. This is a way to do it.

Related