сравнить значения двух массивов на равенство | индекс к индексу |

Вопрос или проблема

У меня есть сценарий, в котором я хочу сравнить значения array1 и array2.

echo "${array1[@]}"

даёт мне output1 : 12.12 10.1

echo "${array2[@]}"

даёт мне output2 : 12.12 10.1

как сравнить значения array1 с array2 следующим образом

array1[0]=array2[0]
array1[1]=array2[1]

12.12 12.12
10.1 10.1

если совпадает, то вывести

echo “успех” или “НЕУДАЧА”

Успех – когда все данные в array1 совпадают с array2 [индекс к индексу]

Неудача – когда значение на индексе не совпадает, тогда неудача

Вы можете просто сравнить массивы как строки:

if [[ "${array1[*]}" == "${array2[*]}" ]]; then
  echo успех
else
  echo НЕУДАЧА
fi

Обратите внимание на использование [*], а не [@] — первое объединяет элементы в одну строку (используя первый символ $IFS в качестве соединителя).


Сравнение как строки может привести к ложным срабатываниям, если некоторые элементы содержат символ соединителя. Например

array1=( "foo bar"  baz )   # 2 элемента
array2=( foo  bar  baz )    # 3 элемента

[[ "${array1[*]}" == "${array2[*]}" ]] && echo равны
# => равны

Более тщательный тест на равенство

  1. проверяет, что массивы имеют одинаковую длину, и
  2. проверяет, что каждый элемент равен:

Эта функция использует namerefs, доступные в (я думаю) bash 4.4 и выше.

arrays_equal() {
    local -n _a1=$1 _a2=$2
    local i    

    # тестировать длину массива
    (( ${#_a1[@]} == ${#_a2[@]} )) || return 1

    # сравнивать элементы
    for ((i = ${#_a1[@]} - 1; i >= 0; i--)); do
        [[ "${_a1[i]}" == "${_a2[i]}" ]] || return 1
    done
    return 0
}

if arrays_equal array1 array2; then
  echo успех
else
  echo НЕУДАЧА
fi

В случае, если элементы не могут содержать \n и вы хотите сделать сравнение, нечувствительное к порядку:

arrays_equal() {
    [ "$1" = a ] || local -n a=$1
    [ "$2" = b ] || local -n b=$2
    (( ${#a[@]} == ${#b[@]} )) || return 1
    [ "`printf '%s\n' "${a[@]}" | sort -t$'\n'`" = "`printf '%s\n' "${b[@]}" | sort -t$'\n'`" ]
}
a=(b c)
b=(c b)
if arrays_equal a b; then
    echo истинно
fi

В случае bash < 4.4 используйте:

[ "`printf '%s\n' ${a[@]+"${a[@]}"} | sort -t$'\n'`" = "`printf '%s\n' ${b[@]+"${b[@]}"} | sort -t'\n'`" ]

Вы не упоминаете, какую оболочку вы используете, но синтаксис выглядит так, будто это оболочка, подобная Korn, скорее всего, bash, где, как и в ksh, индексы массивов начинаются с 0, а массивы являются разреженными, поэтому более напоминают ассоциативные массивы с ключами, ограниченными положительными целыми числами.

С bash 5.1 или новее вы можете сравнить вывод "${array[@]@K}", который выглядит так:

$ bash -c $'a[5]=a a[1]= a[123]="\n"; printf "%s\n" "${a[@]@K}"'
1 "" 5 "a" 123 $'\n'

Где ключи и цитированные значения чередуются и разделяются пробелами.

if [[ "${a[@]@K}" = "${b[@]@K}" ]]; then
  echo a и b имеют один и тот же список ключей и значений
fi

С более старыми версиями вы могли бы сравнить вывод declare -p после замены имени переменной на заполнитель или удаления его, или предполагая, что вы можете гарантировать, что переменные определены и являются массивами, удалить всё до =:

$ bash -c $'a[5]=a a[1]= a[123]="\n"; declare -p a'
declare -a a=([1]="" [5]="a" [123]=$'\n')
a_declare=$(declare -p a)
b_declare=$(declare -p b)

shopt -s extglob
if [[ "${a_declare/ +([^-=])}" = "${b_declare/ +([^-=])}" ]]; then
  echo Переменные идентичны по атрибутам, ключам и значениям
fi

Если есть символ, о котором вы знаете, что он не встречается в элементах массива, вы также можете использовать строковое сравнение для списка ключей и списка значений после объединения с этим символом:

IFS='|'
if [[ "${!a[*]}" = "${!b[*]}" && "${a[*]}" = "${b[*]}" ]]; then
  echo a и b имеют один и тот же список ключей и значений
fi

Для справки: с zsh, которая не может быть оболочкой, которую вы используете, поскольку индексы ее массивов начинаются с 1, а не с 0, и где массивы являются обычными массивами, вы можете просто сравнить ${(q)array}, которые развернутся в элементы, каждый из которых будет заключен в кавычки (и объединены с первым символом $IFS, когда не в списочном контексте, как обычно, хотя вы можете явно объединить это с произвольным символом, как показано в ответе на Linux инструменты для обработки файлов как множеств и проведения операций над множествами на них).

if [[ ${(q)a} = ${(q)b} ]]; then
  echo a и b имеют один и тот же список элементов в одном и том же порядке.
fi

Ответ или решение

Для сравнения значений двух массивов array1 и array2 по индексам, вы можете использовать следующий подход на языке Bash. Данный код проверит, сопоставляются ли значения по индексам и выведет "success", если все значения совпадают, или "FAIL", если хотя бы одно значение не совпадает.

Пример кода:

# Объявляем массивы
array1=(12.12 10.1)
array2=(12.12 10.1)

# Функция для сравнения массивов
arrays_equal() {
    local -n _a1=$1 _a2=$2
    local i    

    # Проверяем длину массивов
    (( ${#_a1[@]} == ${#_a2[@]} )) || return 1

    # Сравниваем элементы по индексам
    for ((i = 0; i < ${#_a1[@]}; i++)); do
        [[ "${_a1[i]}" == "${_a2[i]}" ]] || return 1
    done
    return 0
}

# Вызов функции для проверки равенства массивов
if arrays_equal array1 array2; then
    echo success
else
    echo FAIL
fi

Объяснение кода:

  1. Объявление массивов: Мы создали два массива array1 и array2 с одинаковыми значениями.

  2. Функция arrays_equal:

    • Использует nameref для создания ссылок на входящие массивы.
    • Сравнивает длину массивов. Если длины не совпадают, функция завершает выполнение с кодом 1.
    • Выполняет поэлементное сравнение каждого значения в массиве. Если найдется хотя бы одно не совпадающее значение, функция также завершает выполнение с кодом 1.
  3. Проверка результатов: После проверки массивов с помощью функции, в зависимости от результата выводится "success" или "FAIL".

Примечания:

  • Убедитесь, что вы используете Bash версии 4.4 или выше, чтобы воспользоваться возможностями nameref.
  • Если один из массивов будет пустым, проверка длины также гарантирует, что вы получите правильный вывод.

Этот метод позволяет эффективно и безопасно сравнивать значения массивов индекс за индексом, что минимизирует вероятность ошибок, связанных с неправильным сравнением.

Оцените материал
Добавить комментарий

Капча загружается...