3

I want a script bash/sh/ksh which compare a lot of variables, maybe in an array, and tell me if variable is empty or not.

I think something like this, it but doesn't work.

ARRAY=(
bash="yes"
cash=""
trash="no"
empty=""
)

for var in "${ARRAY[@]}"; do
if [ "$var" == "$empty" ]
then
echo "$var is empty"
else
echo "$var is not empty"
fi
done

I want an output like this

bash is not empty
cash is empty...
1
  • If you run declare -p ARRAY, you'll get a result like declare -a ARRAY='([0]="bash=yes" [1]="cash=" [2]="trash=no" [3]="empty=")', showing that your keys are currently 0, 1, 2 and 3, vs the presumably-intended values of bash, cash, trash and empty. Commented Oct 3, 2016 at 23:27

2 Answers 2

3

If you're willing to limit your runtime environment to a recent version of bash (or modify the code to support ksh93's equivalent syntax),

#!/bin/bash
#      ^^^^ -- specifically, bash 4.0 or newer

declare -A array # associative arrays need to be declared!
array=( [bash]="yes" [cash]="" [trash]="no" [empty]="" )

for idx in "${!array[@]}"; do
  if [[ ${array[$idx]} ]]; then
    echo "$idx is not empty"
  else
    echo "$idx is empty"
  fi
done

To iterate over keys in an array, as opposed to values, the syntax is "${!array[@]}", as opposed to "${array[@]}"; if you merely iterate over the values, you don't know the name of the one currently being evaluated.


Alternately, let's say we aren't going to use an array at all; another way to set a namespace for variables you intend to be able to treat in a similar manner is by prefixing them:

#!/bin/bash

val_bash=yes
val_cash=
val_trash=no
val_empty=

for var in "${!val_@}"; do
  if [[ ${!var} ]]; then
    echo "${var#val_} is not empty"
  else
    echo "${var#val_} is empty"
  fi
done

This works (on bash 3.x as well) because "${!prefix@}" expands to the list of variable names starting with prefix, and "${!varname}" expands to the contents of a variable whose name is itself stored in the variable varname.

Sign up to request clarification or add additional context in comments.

1 Comment

Maybe you should include a shebang line, as the question mentions "bash/sh/ksh".
2

Iterate over the array elements, and inside the loop for read set IFS as = to get variable and it's value in two separate variables, then check if the value is empty:

for i in "${array[@]}"; do 
    IFS== read var value <<<"$i"
    if [ -z "$value" ]; then
        echo "$var is empty"
    else
        echo "$var is not empty"
    fi
done

Outputs:

bash is not empty
cash is empty
trash is not empty
empty is empty

2 Comments

If the OP's data structure is really immutible, and intended to be exactly what it is in the question, then this is certainly correct. I'm not sure that's the case, though -- they talk about being willing to accept any sh/ksh/bash solution, so surely they're flexible on syntax. If the goal is to choose a syntax that's the Right Tool For The Job, then I'd argue that an associative array is the only sensible choice: Who wants to need to iterate through a numerically-indexed array to find the variable they want?
@CharlesDuffy I second. An associative array is the right data structure here.

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.