如何按列对脚本进行排序并删除重复的脚本

如何按列对脚本进行排序并删除重复的脚本

我有一个将近 2000 行的文件。文件格式是这样的:

12 34
0 2
2 3
7 9
1 2
306 237
0 9
12 134
2 7
2 9
306 3
  

我正在尝试编写一个 bash 脚本来删除重复的第一列并按第二列进行组织。我期望这个输出:

0 2 9 
1 2
2 3 7 9
7 9 
12 34 134
306 237 3

我尝试了一些代码,但没有得到所需的输出。我怎样才能实现这一目标以及我应该使用什么?

答案1

您可以使用sortuniq删除重复的行,然后使用awk由第一列值索引的数组,然后将第二列附加到数组的每个值,例如:

sort test.txt | uniq | awk '{if(col[$1])col[$1]=col[$1]" "$2; else col[$1]=$2;}; END{for (i in col) print i, col[i]}'

test.txt你的输入文件。

请注意,在将新列添加到数组的正确值之前,您必须检查数组是否为空,只是在值之间添加空格。

答案2

awk你一起可以做到:

awk '{ found[$1]= (found[$1]? found[$1] FS $2: $2); };
END  { for (x in found) print x, found[x]; }' infile

连接具有相同第一列的第二列,并将其保存在一个关联的数组中,我们将其命名为found,在END打印第一列时(我们将其用作数组键我们将通过以下方式访问它们key我们命名为 if x),接下来是它们连接的第二列(可通过array_name[key]

答案3

使用datamash

$ datamash -s -t ' ' -g 1 collapse 2 <file
0 2,9
1 2
12 34,134
2 3,7,9
306 237,3
7 9

这将读取以空格分隔的数据,对其进行排序,并将第二列折叠为第一列给出的组。

要将逗号替换为空格,请将输出传递给tr , ' '

$ datamash -s -t ' ' -g 1 collapse 2 <file | tr , ' '
0 2 9
1 2
12 34 134
2 3 7 9
306 237 3
7 9

您想按数字对行进行排序吗?将它们传递给sort -n

$ datamash -s -t ' ' -g 1 collapse 2 <file | tr , ' ' | sort -n
0 2 9
1 2
2 3 7 9
7 9
12 34 134
306 237 3

或者,首先进行数字排序,然后-s从调用中删除datamash

$ sort -n <file | datamash -t ' ' -g 1 collapse 2 | tr , ' '
0 2 9
1 2
2 3 7 9
7 9
12 134 34
306 237 3

要按列对每一行进行数字排序(第一列除外),请确保原始数据不仅在第一列上排序,而且还在第二列上排序:

$ sort -k 1,1n -k 2,2n <file | datamash -t ' ' -g 1 collapse 2 | tr , ' '
0 2 9
1 2
2 3 7 9
7 9
12 34 134
306 3 237

(请注意这对最后两行输出造成的差异。)

答案4

对文件的两个字段进行数字排序并传递到 GNU awk/sed 进行进一步处理,我们得到所需的 o/p:

$ sort -n -k1 -k2 < file \
| awk '
    BEGIN { ORS = "" }
    prev != $1"" {
      if (NR>1) print RS
      print
      prev = $1
      next
    }{ print ORS, $2 }
    END { print RS }
' -

$ sort -n -k1 -k2 < file \
| sed -Ee '
  :a
  $!N
  /^(\S+)\s.*\n\1\s/s/\n\S+//
  ta
  P;D
'

输出:

0 2 9
1 2
2 3 7 9
7 9
12 34 134
306 3 237

相关内容