Если вы строго хотите Array1 - Array2
, то
Array1=( "key1" "key2" "key3" "key4" "key5" "key6" "key7" "key8" "key9" "key10" )
Array2=( "key1" "key2" "key3" "key4" "key5" "key6" )
Array3=()
for i in "${Array1[@]}"; do
skip=
for j in "${Array2[@]}"; do
[[ $i == $j ]] && { skip=1; break; }
done
[[ -n $skip ]] || Array3+=("$i")
done
declare -p Array3
Время выполнения можно было бы улучшить с помощью ассоциативных массивов, но лично я бы не стал заморачиваться. Если вы манипулируете достаточным количеством данных, чтобы это имело значение, оболочка — не тот инструмент.
Для симметричной разницы, такой как ответ Денниса, существующие инструменты, такие как comm
, работают, если мы немного массируем ввод и вывод (поскольку они работают со строковыми файлами, а не с переменными оболочки).
Здесь мы указываем оболочке использовать символы новой строки для объединения массива в одну строку и отбрасывать табуляцию при чтении строк из comm
обратно в массив.
$ oldIFS=$IFS IFS=$'\n\t'
$ Array3=($(comm -3 <(echo "${Array1[*]}") <(echo "${Array2[*]}")))
comm: file 1 is not in sorted order
$ IFS=$oldIFS
$ declare -p Array3
declare -a Array3='([0]="key7" [1]="key8" [2]="key9" [3]="key10")'
Он жалуется, потому что при лексографической сортировке key1 < … < key9 > key10
. Но поскольку оба входных массива отсортированы одинаково, можно игнорировать это предупреждение. Вы можете использовать --nocheck-order
, чтобы избавиться от предупреждения, или добавить | sort -u
внутри подстановки процесса <(…)
, если вы не можете гарантировать порядок и уникальность входных массивов.
person
ephemient
schedule
23.02.2010