我有一个将近 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
您可以使用sort
和uniq
删除重复的行,然后使用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