Проверка наличия повторяющихся значений в массиве

Экспортировать значение через среду, а затем расширить его во внутренней оболочке. Предполагая, что оболочка входа username- Bourne -как¹:

$ export path_value=/home/username/filename\$1.class
$ su username -c 'echo "$path_value"'
/home/username/filename$1.class

Это будет работать, даже если переменная содержит кавычки, но не будет работать, если используемая команда очищает среду. Я не думаю, что suдолжен это делать, но sudoможет.

Если мы знаем, что переменная не может содержать одинарные кавычки², то достаточно -одинарного цитирования расширенной строки во внутренней оболочке:

$ path_value=/home/username/filename\$1.class
$ su username -c "echo '$path_value'"
/home/username/filename$1.class

(Обратите внимание, что кавычки стоят в обратном порядке.)


¹ если оболочка входа usernamecshили tcsh, замените echo "$path_value"на echo $path_value:q; если это rcили производная, с echo $path_value.

² и символы новой строки, если оболочка входа пользователя — cshили tcsh, и что она не содержит байтов, не образующих допустимых символов, если оболочка входа пользователя — yash. Также имейте в виду, что аргументы, начинающиеся с -или содержащие обратную косую черту, будут проблемой с echo, лучше использовать printf '%s\n'для произвольных данных

0
25.08.2020, 22:33
3 ответа

В оболочке zsh:

array=(1 2 3 4 3 3)
if (($#array != ${#${(u)array}})); then
  print -u2 array contains duplicates
  exit 1
fi

Где ${(u)array}расширяется до уникальных элементов массива, поэтому мы просто сравниваем количество элементов с количеством уникальных элементов.

Оболочка bashне имеет эквивалента, но поскольку ее массивы в любом случае не могут содержать байты NUL, если вы работаете в системе GNU, вы можете сделать что-то вроде:

readarray -td '' dups < <(
  (( ${#array[@]} == 0 )) ||
    printf '%s\0' "${array[@]}" |
      LC_ALL=C sort -z |
      LC_ALL=C uniq -zd
)

if ((${#dups[@]} > 0)); then
  echo >&2 "array has duplicates:"
  printf >&2 ' - "%s"\n' "${dups[@]}"
  exit 1
fi

В них элементы считаются дубликатами , если они идентичны по байтам -по -байтам, а не в том случае, если их числовые значения совпадают (1, 01, 0x1. ], 1e0, 2-1, $'1\n', ' 1'считаются разными ).

5
18.03.2021, 23:10

Предполагая, что arrсодержит только целые числа и что числа, дополненные нулями, следует считать дубликатами (например, 01является дубликатом 1), мы можем использовать второй массив, чтобы сохранить значения, уже "видимые", когда разбор каждого элемента первого массива arr.

#!/bin/bash
arr=(1 2 3 4 3 3)
seen=()

for i in "${arr[@]}"; do
    #Remove padding zeroes, if any
    i=$((10#$i))
    # If element of arr is not in seen, add it as a key to seen
    if [ -z "${seen[i]}" ]; then
        seen[i]=1
    else
        echo "Array contains a duplicate."
        break
    fi
done
2
18.03.2021, 23:10

Предполагая, что ваш key_arrayмассив всегда содержит только целые числа (положительные целые числа ), мы можем использовать тот факт, что обычные массивы разрежены в оболочке bash. Следующий код перебирает массив ключей, создавая экземпляры элементов в обычном массиве, пока мы не найдем ключ, который мы уже обработали:

key_array=( '09' 1 2 3 4 3 3 '04' '001' '07' )

has_dupes () (
        unset -v a

        for key do
                ${a[10#$key]+'return'}  # execute "return" if a[10#$key] is set
                a[10#$key]=             # set a[10#$key] to empty string
        done

        return 1
)

if has_dupes "${key_array[@]}"; then
        echo 'array has dupes'
else
        echo 'array has no dupes'
fi

Это вводит вспомогательную функцию has_dupes, которая принимает список целых чисел и возвращает ноль, если в списке есть повторяющееся значение, и не -ноль, если повторяющихся значений нет.

Расширение стандартного параметра ${variable+word}используется для вставки слова return, если ранее было установлено a[10#$key]. При подстановке returnвыполнение функции прекращается, и вызывающему объекту возвращается нулевой статус выхода, означающий, что мы нашли повторяющееся значение. Индекс 10#$keyозначает «значение $key, интерпретируемое как целое число с основанием 10» и позволяет нам приравнять такие ключи, как 03и 3.

0
25.09.2021, 14:13

Теги

Похожие вопросы