Bash
測試數組中是否存在重複值
我試圖找到一種簡單的方法來測試數組中的重複值。能夠辨識具有重複項的特定行會很好,但並非完全必要,但重要的是能夠看到存在重複項。
我有一個數組,
$key_array
其中包含一些數字:# echo ${key_array[@]} 1 2 3 4 3 3
這個數組可以有任意數量的數字,其中一些可能是其他的重複。它們將只是整數。(以 a 開頭的數字
0
,例如03
,根本不應該進入數組,但如果發生這種情況的機會不大,擷取3
和03
作為彼此的副本將比將它們視為不同的數字更好。)我需要確定這些數字是否重複。我在想如果沒有別的,這可以用退出程式碼來完成。我所追求的是這樣的:
if $(some command); then echo "Array contains duplicates." exit 1 fi $(commands to run after duplicate check)
最後的想法是腳本通知使用者並在有重複項時退出(辨識重複項在哪裡不是超級重要,只是告訴使用者檢查重複項就足夠了),或者如果沒有任何重複項,它繼續執行並執行許多其他東西。
我將如何最好地做到這一點?
假設
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
在
zsh
外殼中:array=(1 2 3 4 3 3) if (($#array != ${#${(u)array}})); then print -u2 array contains duplicates exit 1 fi
Where
${(u)array}
擴展為數組的唯一元素,因此我們只是將元素的數量與唯一元素的數量進行比較。
bash
shell 沒有等價物,但由於它的數組無論如何都不能包含 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'
都被認為是不同的)。