按列和行对BASH脚本中的数组进行排序,同时保持它们不变

时间:2015-01-13 06:41:50

标签: arrays bash sorting

我有一个如下所示的测试文件:

1   1   1   1   1
9   3   4   5   5
6   7   8   9   7
3   6   8   9   1
3   4   2   1   4
6   4   4   7   7

每一行都应该代表学生的成绩。因此,用户输入了一个' r'或者是' c'在命令行中选择按行或列排序,后跟文件名。按行排序表示获得学生平均值,排序列表将代表特定的作业平均值。

我还没有对选择变量做任何事情,因为我需要先对数组进行排序,这样我就可以取平均数,然后得到每列和每行的中位数。

所以我不确定如何选择按这些特定选项排序。以下是我到目前为止的情况:

#!/bin/bash
choice="$1"
filename="$2"
c=0
if [ -e "$filename" ]
then
      while read line
      do
         myArray[$c]=$line
         c=$(expr $c + 1)
         done < "$filename"
 else
     echo "File does not exist"
fi
printf -- '%s\n' "${myArray[@]}"
FS=$'\n' sorted=($(sort -n -k 1,1<<<"${myArray[*]}"))
echo " "
printf '%s\n' "${sorted[@]}"

这只是排序第一列,我不知道为什么它甚至这样做。任何正确方向的推动都将受到赞赏。举例来说,这将有所帮助,谢谢!

更新: 随着建议的变化我到目前为止:

#!/bin/sh

IFS=$'\n';

choice="$1"

filename="$2"

if [ -e "$filename" ]

then
        while read line

        do
                myArray[$c]=$line

                c=$(expr $c + 1)

        done < "$filename"

else
        echo "File does not exist."
fi

printf -- '%s\n' "${myArray[@]}"

width=${myArray[0]// /}

width=${#width}

height=${#myArray[@]}

bar=()

for w in $(seq 0 1 $((${width}-1)))

do
        tmp=($(sort -n <<<"${myArray[*]}"))

        for h in $(seq 0 1 $((${height}-1)))

        do
                myArray[h]=${myArray[h]#* }

                bar[h]="${bar[h]} ${tmp[h]%% *}"

                bar[h]="${bar[h]# }"

        done
done

printf -- '%s\n' "${bar[*]}"

但是现在我得到了一些非常奇怪的输出,比我开始的数字和看似随机的顺序。

1 个答案:

答案 0 :(得分:0)

实际上它正在排序$ line(s)是字符串。您需要初始化列以正确排序,以便它是一个数组

更新:

以下代码非常简单。没有考虑性能方面。因此,对于大型数据集,这将需要一段时间才能按列排序。 您的数据集必须包含由单个空格分隔的数字行才能使其正常工作。

#!/bin/bash

IFS=$'\n';

# here you can place your read line function
ar[0]="5 3 2 8"
ar[1]="1 1 1 1"
ar[2]="3 2 4 5"
printf -- '%s\n' "${ar[*]}" # print the column wise unsorted ar
echo

# sorting
width=${ar[0]// /}
width=${#width}
height=${#ar[@]}

bar=()
for w in $(seq 0 1 $((${width}-1))); do # for each column
  #sort -n <<<"${ar[*]}" # debug, see first column removal
  tmp=($(sort -n <<<"${ar[*]}")) # this just sorts lexigraphically by "first column"
                                 # rows are strings, see initial definition of ar
  #echo
  for h in $(seq 0 1 $((${height}-1))); do # update first column
    ar[h]=${ar[h]#* } # strip first column
    bar[h]="${bar[h]} ${tmp[h]%% *}" # add sorted column to new array
    bar[h]="${bar[h]# }" # trim leading space
  done
  #printf -- '%s\n' "${bar[*]}" # debug, see growing bar
  #echo "---"
done

printf -- '%s\n' "${bar[*]}" # print the column wise sorted ar

打印出未排序和排序的数组

5 3 2 8
1 1 1 1
3 2 4 5

1 1 1 1
3 2 2 5
5 3 4 8