在 Bash 中创建数组的数组并按派生值排序

Creating Arrays of Arrays in Bash and Sorting By Derived Values

我在 Bash 中创建和排序数组时遇到问题,该数组将其内容作为命令中的行,获取每一行的某些部分并对它们进行操作,然后再将它们附加到数组。

为了澄清,命令 "bogoutil -d wordlist.db" 以这种形式给出输出:

hello 428 3654 20151116

除了有几百万行。

我想将命令的每一行输出加载到一个数组中,取第一个数字减去第二个数字的绝对值,将该值附加到新数组中的行,然后按该值对新数组进行排序新值。

我遇到的问题是我怀疑 IFS 需要更改为“\n”以将每行 bogoutil 输出放入一个数组,但随后它需要再次更改以标记第二个和每行中的第三个整数。到目前为止很难弄清楚我的错误是什么,因为数组中有超过 1000 万行,但我可以从输出中看出这不是我应该得到的 - 我认为它只是列出每一行并且没有正确标记。通常它会运行一段时间,将大量输出打印到 shell 中,这绝对不是我所期望的(我认为它只是一些标记,但绝对不是全部)然后打印

sort: cannot read: resultsarray: No such file or directory

这是我到目前为止所写的内容

#!/bin/bash

IFS=$"\n" #set the IFS so it tokenises each line in the command
for i in $( bogoutil -d wordlist.db )
    do 
            echo $i
            OUTPUT=( ${i// \n} ) #swap out space for a newline so i can
                                 #tokenise by spaces
            BAD=${OUTPUT[1]}
            echo $BAD
            GOOD=${OUTPUT[2]}
            echo $GOOD
            DIFF=$GOOD-$BAD
            echo $DIFF
            if [ "$DIFF" -lt "0" ]
            then
                    DIFF=$DIFF \* -1
            fi
            NEWOUT="$OUTPUT $DIFF" #append the abs of the difference to
                                   #the line so i can sort by it
            resultsarray[i]=$NEWOUT
    done

sort -t " " -k 5 -g resultsarray

echo "${resultsarray[@]:0:10}"

如有任何帮助,我们将不胜感激。我真的被难住了,不知道为什么它不起作用。我怀疑这与我尝试标记每一行输出的方式有关,但我不确定。另一种可能性(假设它列出标记一段时间然后就停止了)是数组中的元素太多了,它用完了分配的 space。有这个可能吗?

在此先致谢,非常感谢您提供的任何帮助。

编辑:澄清预期的输入和输出。

示例输入为

hello 4 1 20151116
goodbye 0 256 20151116
grant 428 3654 20151116

预期的输出是

grant 428 3654 20151116 3226
goodbye 0 256 20151116 256
hello 4 1 20151116 3

如您所见,它按第一个和第二个数字之差的绝对值排序。数据集中没有负数,最低为0.

编辑:下面的 awk 解决方案效果很好!我不确定如何使用 Bash,但我怀疑 bash 不是解决此问题的正确方法,无论如何使用 awk 可能更好。感谢大家的帮助,非常感谢!

如果我正确理解你的问题(这就是为什么包含你的样本输入的样本输出如此​​重要),

 cat tst.file
 hello 428 3654 20151116
 goodby -428 3655 20151116

这是假设输入不是制表符分隔的数据。另外,如果您想用稍大的数据集更新您的问题,我很乐意尝试确认这是一个很好的解决方案。您可能还想从输入中包含所需的输出 ;-)(提示,提示)。

 awk '
    function abs( num) {return (num >0) ? -num : num;} 
    {res=abs()+ ; print [=11=] "\t" res}' tst.file \
 | sort -t"${tabChar}" -k2n

产生类似

的输出
hello 428 3654 20151116    3226
goodby -428 3655 20151116  3227

一些sort程序支持-t"\t"为排序分隔符定义一个tabChar。我的不是这样,我像 tabChar=" " 一样单独定义它,其中它是 dbl-quotes 中的真实制表符 Char。


正如我在评论中提到的,您可以简化上面的操作(假设您的程序以标准行结尾),例如:

bogoutil -d wordlist.db \
| awk '....' \
| sort -k2n

IHTH