Bash

合併關聯數組 BASH 中的重複鍵

  • June 21, 2019

我有一個包含重複項的數組,例如

THE_LIST=(
"'item1' 'data1 data2'"
"'item1' 'data2 data3'"
"'item2' 'data4'"
)

基於上述,我想創建一個關聯數組,將其分配itemN為鍵和dataN值。

我的程式碼遍歷列表,並像這樣分配 key => 值(附加功能被縮短,因為它在列表上執行一些額外的工作):

function get_items(){
   KEY=$1
   VALUES=()
   shift $2
   for VALUE in "$@"; do
       VALUES[${#VALUES[@]}]="$VALUE"
   done
}

declare -A THE_LIST
for ((LISTID=0; LISTID<${#THE_LIST[@]}; LISTID++)); do
   eval "LISTED_ITEM=(${THE_LIST[$LISTID]})"
   get_items "${LISTED_ITEM[@]}"
   THE_LIST=([$KEY]="${VALUES[@]}")
done

當我列印數組時,我得到類似:

item1: data1 data2
item1: data2 data3
item2: data4

但相反,我想得到:

item1: data1 data2 data3
item2: data4

找不到合併重複鍵以及刪除鍵的重複值的方法。

這裡的方法是什麼?

更新

實際程式碼是:

THE_LIST=(
"'item1' 'data1 data2'"
"'item1' 'data2 data3'"
"'item2' 'data4'"
)

function get_backup_locations () {
 B_HOST="$2"
 B_DIRS=()
 B_DIR=()
 shift 2

 for B_ITEM in "$@"; do
   case "$B_ITEM" in
     -*) B_FLAGS[${#B_FLAGS[@]}]="$B_ITEM" ;;
     *) B_DIRS[${#B_DIRS[@]}]="$B_ITEM" ;;
   esac
 done

 for ((B_IDX=0; B_IDX<${#B_DIRS[@]}; B_IDX++)); do
   B_DIR=${B_DIRS[$B_IDX]}

   ...do stuff here...

 done
}

function get_items () {
 for ((LOCIDY=0; LOCIDY<${#LOCATIONS[@]}; LOCIDY++)); do
   eval "LOCATION=(${LOCATIONS[$LOCIDY]})"
   get_backup_locations "${LOCATION[@]}"
   THE_LIST=([$B_HOST]="${B_DIR[@]}")
 done | sort | uniq
}

列印數組時:

for i in "${!THE_LIST[@]}"; do
   echo "$i : ${THE_LIST[$i]}"
done

我明白了

item1: data1 data2
item1: data2 data3
item2: data4

如果保證鍵和值是純字母數字的,那麼這樣的事情可能會起作用:

declare -A output

make_list() {
 local IFS=" "
 declare -A keys                  # variables declared in a function are local by default
 for i in "${THE_LIST[@]}"
 do 
   i=${i//\'/}                    # since everything is alphanumeric, the quotes are useless
   declare -a keyvals=($i)        # split the entry, filename expansion isn't a problem
   key="${keyvals[0]}"            # get the first value as the key
   keys["$key"]=1                 # and save it in keys
   for val in "${keyvals[@]:1}"
   do                             # for each value
     declare -A "$key[$val]=1"    # use it as the index to an array. 
   done                           # Duplicates just get reset.
 done

 for key in "${!keys[@]}"
 do                               # for each key
   declare -n arr="$key"          # get the corresponding array
   output["$key"]="${!arr[*]}"    # and the keys from that array, deduplicated
 done
}

make_list
declare -p output  # print the output to check

通過範例輸入,我得到以下輸出:

declare -A output=([item1]="data3 data2 data1" [item2]="data4" )

數據項無序,但已刪除重複數據。


最好將 Python 與csv模組一起使用。

引用自:https://unix.stackexchange.com/questions/524601