如何使用Unix排序进行自定义排序?


11

我正在使用unix sort对具有多个列的逗号分隔文件进行排序。到目前为止,这对于按数字或字母顺序对数据进行排序非常有效:

任何排序之前的示例文件:

C,United States,WA,Tacoma,f,1
A,United States,MA,Boston,f,0
B,United States,NY,New York,f,5
A,Canada,QC,Montreal,f,2
A,Bahamas,Bahamas,Nassau,f,2
A,United States,NY,New York,f,1

排序文件: $ sort -t ',' -k 2,2 -k 3,3 -k 4,4 -k 5,5r -k 6,6nr tmp.csv

排序结果:

A,Bahamas,Bahamas,Nassau,f,2
A,Canada,QC,Montreal,f,2
A,United States,MA,Boston,f,0
B,United States,NY,New York,f,5
A,United States,NY,New York,f,1
C,United States,WA,Tacoma,f,1

问题是:我想根据自定义排序对第2列进行排序,这意味着我要首先是美国,然后是加拿大,然后是巴哈马:

所需的排序:

A,United States,MA,Boston,f,0
B,United States,NY,New York,f,5
A,United States,NY,New York,f,1
C,United States,WA,Tacoma,f,1
A,Canada,QC,Montreal,f,2
A,Bahamas,Bahamas,Nassau,f,2

有什么方法可以通过unix排序,然后可以应用自定义排序顺序?就像是: $ sort -t ',' -k 2,2:'United States, Canada, Bahamas' -k 3,3 -k 4,4 -k 5,5r -k 6,6nr tmp.csv

谢谢!


3
对于这三个值,您需要反向字母顺序。对于一般情况,您需要将名称映射到排序顺序号,然后使用排序顺序号进行排序。或者选择一种脚本语言...一种可能性是join命令,但是最终可能会导致很多排序-的输入文件join必须按一个顺序排序,然后您将sort再次使用它来将数据放入一个不同的顺序(并且在排序后步骤中丢失了排序顺序列)。
乔纳森·勒夫勒

在您的示例输入中,是否应该在最后一行t而不是f
Lev Levitsky

利夫:是的,很好。我的错; 太多的剪切和粘贴(我的实际数据集很大,并且我不小心抓住了错误的行)。

我更新了答案以匹配您的数据。
Lev Levitsky

Answers:


8

另一个答案和注释通常回答这个问题,这是实现的样子:

$ cat order
Bahamas,3
Canada,2
United States,1

$ cat data
C,United States,WA,Tacoma,f,1
A,United States,MA,Boston,f,0
B,United States,NY,New York,f,5
A,Canada,QC,Montreal,f,2
A,Bahamas,Bahamas,Nassau,f,2
A,United States,NY,New York,f,1

$ sort -t, -k2 data | join -t, -11 -22 order - | sort -t, -k2n -k4,5 -k6r -k7nr | cut -d, -f 3,1,4-7
A,United States,MA,Boston,f,0
B,United States,NY,New York,f,5
A,United States,NY,New York,f,1
C,United States,WA,Tacoma,f,1
A,Canada,QC,Montreal,f,2
A,Bahamas,Bahamas,Nassau,f,2

太好了,谢谢您的帮助。这很好用!

@jewelia再次改进,sed在这里并不需要。
Lev Levitsky

1

你不能用sort做到这一点。在这一点上,您确实应该接触awk / perl /您的选择语言。不过,您可以捏造它。例如,您可以使用sed将“美国”更改为0,将“加拿大”更改为1,将“巴哈马”更改为2,然后对该列进行数字排序,然后将其重新设置。或将“美国”更改为“美国,0”等,对多余的列进行排序,然后将其丢弃。


0

我只是写了一个名为csort的助手来简化此操作。它根据行内的子字符串或正则表达式匹配项,为每行加上您选择的值作为前缀:

$ csort -t, '2=United States' X 2=Canada Y 2=Bahamas Z < tmp.csv | \
sort -t, -k1,1 -k3,3 -k4,4 -k5,5 -k6,6r -k7,7nr
X,A,United States,MA,Boston,f,0
X,B,United States,NY,New York,f,5
X,A,United States,NY,New York,f,1
X,C,United States,WA,Tacoma,f,1
Y,A,Canada,QC,Montreal,f,2
Z,A,Bahamas,Bahamas,Nassau,f,2

2=STR符号的意思是“匹配,如果第二个字段等于STR”。

然后,您可以选择通过管道传递输出cut -c3-以删除前缀。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.