Bash как вставить в массив, если массив не содержит значения внутри оператора if - PullRequest
0 голосов
/ 03 августа 2020

У меня есть функция, чтобы проверить, есть ли что-то в массиве:

function inArray() {
    local val="$1"
    shift
    local array=("$@")
    for i in "${array[@]}"; do
        if [ "${i}" == "${val}" ]; then
            return 0
        fi
    done
    return 1
}

И оператор if, чтобы попытаться вставить значения в noDupe, только если у него еще нет этого значения:

noDupe=()
values=("test" "test" "test2")
for value in ${values[@]}; do
    if [ $(inArray "${value}" "${values[@]}") -eq 1 ]; then
        noDupe+="{value}"
    fi
done

Моя текущая ошибка в том, что -eq ожидает унарный оператор. Я попытался изменить его на ==, но это только для строк, а не 0 s и 1 s, которые моя функция возвращает. Как заставить работать оператор if?

Ответы [ 3 ]

1 голос
/ 03 августа 2020

Функция поиска по массиву может стать узким местом, если длина массива велика. В качестве альтернативы рассмотрите возможность использования ассоциативного массива bash. Это упростит код и ускорит выполнение, уменьшив сложность с O (n ^ 2) до O (n log n).

Логика без дублирования c может быть реализована без необходимости писать функция inArray.

declare -A v_temp
values=("test" "test" "test2")
for value in ${values[@]}; do
    v_temp[$value]=1
done
noDupe=(${!v_temp[@]})
1 голос
/ 03 августа 2020

Ваша функция использует возвращаемые значения, но вы пытаетесь использовать ее так, как если бы возвращаемые значения были напечатаны. Правильное использование для «если статус выхода ненулевой» упрощается до

if ! inArray "${value}" "${values[@]}"; then

Боковое примечание: вы получаете ошибку не в том, что -eq ожидает унарный оператор, это

bash: [: -eq: unary operator expected

означает, что [ ожидал унарный оператор, но вместо этого получил -eq , бинарный оператор. Это связано с тем, что ваша подстановка команд не заключена в кавычки, и когда команда ничего не возвращает, ваш тест становится

[ -eq 1 ]

При правильном цитировании

[ "$(inArray "${value}" "${values[@]}")" -eq 1 ]

тест будет жаловаться, что он ожидает целое число выражение (но вместо этого получает пустую строку), потому что оно расширяется до

[ "" -eq 1 ]
0 голосов
/ 03 августа 2020

Рассмотрим этот метод, используя $BASH_REMATCH:

inArray () {
    re="_S_$1 | $1 | ${1}_E_"
    [[ "_S_${array[@]}_E_" =~ $re ]] && return 0 || return 1
}

И имя массива также может быть отправлено как arg этой функции:

inArray () {
    name="$1[@]"
    re="_S_$2 | $2 | ${2}_E_"
    [[ "_S_${!name}_E_" =~ $re ]] && return 0 || return 1
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...