在 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
我在 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