Bash проверить, есть ли у массива переменных значения или нет - PullRequest
2 голосов
/ 28 февраля 2020

У меня есть массив переменных. Я хочу проверить, имеют ли переменные значение, используя for для l oop.

Я получаю значения в l oop, но условие if не выполняется

function check {
    arr=("$@")
    for var in "${arr[@]}"; do
        if [ -z $var ] ; then
            echo $var "is not available"
        else
            echo $var "is available"
        fi
    done
}

name="abc"
city="xyz"
arr=(name city state country)
check ${arr[@]}

Для выше я получаю все как доступно

Ожидаемый вывод

name is available
city is available
state is not available
country is not available

Ответы [ 2 ]

4 голосов
/ 28 февраля 2020

Это правильный синтаксис для вашей задачи

if [ -z "${!var}" ] ; then
    echo $var "is not available"
else
    echo $var "is available"
fi

Пояснение, этот метод использует косвенное расширение переменной, эта конструкция ${!var} будет расширяться как значение переменной, имя которой находится в $var.

Изменена check функция немного

check () {
    for var in "$@"; do
        [[ "${!var}" ]] && not= || not="not "
        echo "$var is ${not}available"
    done
}

И еще один вариант с использованием declare

check () {
    for var in "$@"; do
        declare -p $var &> /dev/null && not= || not="not "
        echo "$var is ${not}available"
    done
}

Из declare help

$ declare --help
declare: declare [-aAfFgilnrtux] [-p] [name[=value] ...]
    Set variable values and attributes.
    Declare variables and give them attributes.  If no NAMEs are given,
    display the attributes and values of all variables.
    ...
    -p  display the attributes and value of each NAME
    ...

На самом деле все вары могут быть проверены одновременно с помощью этого

check () {
    declare -p $@ 2>&1 | sed 's/.* \(.*\)=.*/\1 is available/;s/.*declare: \(.*\):.*/\1 is not available/'
}
0 голосов
/ 28 февраля 2020

Хотя косвенное обращение является возможным решением, на самом деле не рекомендуется для использования. Более безопасный способ - использовать ассоциативный массив:

function check {
    eval "declare -A arr="${1#*=}
    shift
    for var in "$@"; do
        if [ -z "${arr[$var]}" ] ; then
            echo $var "is not available"
        else
            echo $var "is available"
        fi
    done
}

declare -A list
list[name]="abc"
list[city]="xyz"

check "$(declare -p list)" name city state country

Возвращает:

name is available
city is available
state is not available
country is not available

Для создания этого ответа был использован следующий вопрос: Как переименовать ассоциативный массив в Bash?

...