我正在使用 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-
以删除前缀。