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

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

我正在使用 unix 排序对包含多个列的逗号分隔文件进行排序。到目前为止,这可以完美地按数字或字母顺序对数据进行排序:

排序前的示例文件:

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,然后可以应用它?类似于: $ sort -t ',' -k 2,2:'United States, Canada, Bahamas' -k 3,3 -k 4,4 -k 5,5r -k 6,6nr tmp.csv

谢谢!

答案1

其他答案和评论一般性地回答了这个问题,下面是实现方式:

$ 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

答案2

你不能这样做种类。此时,你真的应该awk/perl/您选择的语言。不过,您可以捏造它。例如,您可以使用 sed 将“美国”更改为 0、将“加拿大”更改为 1、将“巴哈马”更改为 2,然后对该列进行数字排序,然后再将其恢复。或者将“美国”更改为“美国,0”等,对额外的列进行排序,然后将其丢弃。

答案3

我刚刚写道一个名为 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-以删除前缀。

相关内容