Как проверить, являются ли значения массива пустыми, массово?

#arrays #bash #variables

#массивы #bash #переменные

Вопрос:

Мне нужен скрипт bash / sh / ksh, который сравнивает множество переменных, возможно, в массиве, и сообщает мне, является ли переменная пустой или нет.

Я думаю, что что-то вроде этого, но это не работает.

 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
  

Я хочу получить такой результат

 bash is not empty
cash is empty...
  

Комментарии:

1. Если вы запустите declare -p ARRAY , вы получите результат, подобный declare -a ARRAY='([0]="bash=yes" [1]="cash=" [2]="trash=no" [3]="empty=")' , показывающий, что ваши ключи в настоящее 0 время, 1 , 2 и 3 , по сравнению с предположительно предполагаемыми значениями bash , cash , trash и empty .

Ответ №1:

Если вы хотите ограничить свою среду выполнения последней версией bash (или изменить код для поддержки эквивалентного синтаксиса ksh93),

 #!/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
  

Для перебора ключей в массиве, в отличие от значений, синтаксис "${!array[@]}" , в отличие от "${array[@]}" ; если вы просто перебираете значения, вы не знаете имя того, которое в данный момент оценивается.


В качестве альтернативы, допустим, мы вообще не собираемся использовать массив; другой способ задать пространство имен для переменных, которые вы собираетесь обрабатывать аналогичным образом, — это добавить к ним префикс:

 #!/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
  

Это работает (в том числе и на bash 3.x), поскольку "${!prefix@}" расширяется до списка имен переменных, начинающихся с prefix , и "${!varname}" расширяется до содержимого переменной, имя которой само хранится в переменной varname .

Комментарии:

1. Возможно, вам следует включить строку shebang, поскольку в вопросе упоминается «bash / sh / ksh».

Ответ №2:

Выполните итерацию по элементам массива и внутри цикла для read set IFS as = , чтобы получить переменную и ее значение в двух отдельных переменных, затем проверьте, является ли значение пустым:

 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
  

Выводит:

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

Комментарии:

1. Если структура данных OP действительно неизменна и предназначена для того, чтобы быть именно такой, какой она есть в вопросе, то это, безусловно, правильно. Я не уверен, что это так, хотя — они говорят о готовности принять любое решение sh / ksh / bash, поэтому, конечно, они гибки в синтаксисе. Если цель состоит в том, чтобы выбрать синтаксис, который является подходящим инструментом для работы, то я бы сказал, что ассоциативный массив — единственный разумный выбор: кому нужно перебирать массив с числовым индексом, чтобы найти нужную переменную?

2. @CharlesDuffy Я второй. Ассоциативный массив — это правильная структура данных здесь.