#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 Я второй. Ассоциативный массив — это правильная структура данных здесь.