【问题标题】:How a sort associative array bash script如何排序关联数组 bash 脚本
【发布时间】:2015-07-03 05:31:18
【问题描述】:

如何在 bash 中对关联数组进行排序?

例如,我在 bash 中有数组:

[0,0]="Max"
[0,1]="25"
[1,0]="Vladimir"
[1,1]="0"
[2,0]="Mayki"
[2,1]="50"

输出必须是:

  1. Mayki - 50
  2. 最大 - 25
  3. 弗拉基米尔 - 0

我不知道如何排序这个数组。

附加信息:我从文本文件(“log.txt”)解析 assoc 数组

    #!/bin/bash

declare -A b_array

# Read the file in parameter and fill the array named "array"
getArray() {

    i=0
    w=9

    count=10

    while read line # Read a line
    do
        k=0
        #array[i]=$line # Put it into the array

        #b_array[$i,0]=$(grep -Eo "(http|https)://[a-zA-Z0-9./?=_-]*" <<<"$line") 

        for word in $line;
          do  
                  #echo $k;
                  #echo $word;
                  if [ "$k" = "$w" ]; then
                      if [ $word != "-" ]; then
                        b_array[$i]=$word 
                        i=$(($i + 1))
                      fi 

                  fi 
                  k=$(($k + 1))
            done


    done < $1
}

getArray "log.txt"

【问题讨论】:

  • 您最好使用具有更好数据结构支持的语言。
  • 输入实际上是什么样的?该示例数组与任何内容有什么关系?你不是在创建一个这样的(bash 做不到)。您在输入中似乎没有这样的内容(尽管这根本不清楚)。关联数组没有顺序,因此您能做的最好的事情就是获取键并对其进行排序,然后遍历该排序的键列表。
  • 这是我KPI大学的功课
  • 原来的任务:我需要解析文件并按字节数显示10行查询。
  • 这是使用关联数组的一种非常奇怪的方式。通常会使用名称作为键:([Max]=25 [Mayki]=50 [Vladimir]=0)

标签: bash sorting associative


【解决方案1】:

有几种方法可以解决这个问题。最简单的方法之一可能是将字符串对读入索引数组,然后对数字字段进行反向数字排序:

#!/bin/bash

declare -A arr
declare -a sa

arr[0,0]="Max"
arr[0,1]="25"
arr[1,0]="Vladimir"
arr[1,1]="0"
arr[2,0]="Mayki"
arr[2,1]="50"

## convert associative array to 
#  indexed array of string pairs
#  (e.g. "Max - 25", "Mayki - 50" )
for i in ${!arr[@]}; do                         # for each key in ar

    x=${i%,*}                                   # separate x,y values
    y=${i#*,}
    (( y == 1 )) && continue                    # if y == 1, continue

    for j in ${!arr[@]}; do                     # for each key in ar

        _x=${j%,*}                              # separate _x,_y values
        _y=${j#*,}
        ((x != _x)) || ((_y == 0)) && continue  # if x != _x, or _y == 0, continue

        sa+=( "${arr[$i]} - ${arr[$j]}" )       # add combined string to indexed sa

    done
done

sort -r -k3 -n <<<"$(printf "%s\n" "${sa[@]}")" # numeric reverse sort sa on key3

exit 0

输出

$ bash sort_assoc.sh
Mayki - 50
Max - 25
Vladimir - 0

【讨论】:

  • 什么错误?我有GNU bash, version 4.3.33 如果这给您带来问题,还有其他方法可以对索引数组进行排序。我检查过,也适用于GNU bash, version 4.2.37(我拥有的最老的)
  • :没有这样的文件或目录h:找不到命令':不是有效的标识符ar ': not a valid identifier sa:找不到命令:找不到命令 sort.sh:第 36 行:语法错误:文件意外结束-bash-4.1$
  • 什么?你确定你完全复制/粘贴了吗?让我们将ar 更改为arr 以不与外部ar 命令冲突(无论如何都不应该)现在试试吧。
  • 对不起,请检查服务器控制台 VPS (4.1) 上的代码。它还在虚拟机上会尝试运行(4.3)。
  • 好的,效果很好。我已经在多台机器(Archlinux 和 openSuSE)上运行以确认。 ar ': not a valid identifiersa : command not found : command not found sort.sh: line 36 错误毫无意义。如果您遇到这些错误,则您的 shell 解释器有问题。让我知道你发现了什么。
【解决方案2】:

我可能会切换到 Perl 来完成如此复杂的任务,即使它在 bash 中仍然可行:

#!/bin/bash

declare -A arr
arr=([0,0]="Max"
     [0,1]="25"
     [1,0]="Vladimir"
     [1,1]="0"
     [2,0]="Mayki"
     [2,1]="50"
     [10,0]=Ivan
     [10,1]=10
    )

indices=( $( (IFS=$'\n' ; echo "${!arr[*]}") | grep ,0 | cut -d, -f1 | sort ) )

for i in "${indices[@]}" ; do
    echo ${arr[$i,0]} ${arr[$i,1]}
done | sort -rnk2

如果你像这样定义数组会简单得多

arr=([Max]=25
     [Vladimir]=0
     [Mayki]=50
     [Ivan]=10
    )

for paren in "${!arr[@]}" ; do
    echo $paren ${arr[$paren]}
done | sort -rnk2

【讨论】:

  • 我有错误: : command not found ': not a valid identifier: arr : command not found : command not found 'est3.sh: line 16: syntax error near unexpected token do 'est3.sh: line 16: `for i in "${indices[@]}" ;做
  • @МаксимБорисов:什么版本的 bash?
  • @МаксимБорисов:应该可以。您是否复制并粘贴了代码?
  • @МаксимБорисов: 被屏蔽在这里:-(
  • @МаксимБорисов: 无法访问:-(
猜你喜欢
  • 2017-05-04
  • 2012-01-03
  • 2021-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-23
  • 1970-01-01
相关资源
最近更新 更多