AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 524601
Accepted
Bart
Bart
Asked: 2019-06-13 23:25:33 +0800 CST2019-06-13 23:25:33 +0800 CST 2019-06-13 23:25:33 +0800 CST

合并关联数组 BASH 中的重复键

  • 772

我有一个包含重复项的数组,例如

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
bash shell-script
  • 2 2 个回答
  • 1065 Views

2 个回答

  • Voted
  1. Best Answer
    muru
    2019-06-14T00:50:00+08:002019-06-14T00:50:00+08:00

    如果保证键和值是纯字母数字的,那么这样的事情可能会起作用:

    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模块一起使用。

    • 1
  2. m0dular
    2019-06-21T21:53:05+08:002019-06-21T21:53:05+08:00

    如果任何值中都没有空格,则此解决方案可能有效。使用awk关联数组来构建declare -A命令。

    #!/bin/bash
    
    THE_LIST=(
    "'item1' 'data1 data2'"
    "'item1' 'data2 data3'"
    "'item2' 'data4'"
    )
    
    eval "$(\
      for i in "${THE_LIST[@]}"; do
        row=($(eval echo $i))
        echo "${row[@]}"
      done | awk '{ for (i=2; i<=NF; i++) if (seen[$1] !~ $i) { seen[$1]=seen[$1]$i" " } }
        END { for (s in seen) print "declare -A new_list["s"]=\""seen[s] }' | sed 's/[[:space:]]*$/"/'
    )"
    
    for i in "${!new_list[@]}"; do
      echo "$i: ${new_list[$i]}"
    done
    

    这打印:

    item2: data4
    item1: data1 data2 data3
    

    值的顺序被保留,但键被重新排序。我不知道如何修剪数组条目的尾随空格,awk所以我只是用sed引号替换它,但它已经是一开始就完全破解了。

    • 1

相关问题

  • 从文本文件传递变量的奇怪问题

  • 虽然行读取保持转义空间?

  • MySQL Select with function IN () with bash array

  • `tee` 和 `bash` 进程替换顺序

  • 运行一个非常慢的脚本直到它成功

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve