按列组排序并忽略此示例中失败的其他列,为什么?

按列组排序并忽略此示例中失败的其他列,为什么?

我无法弄清楚为什么sort不能正常工作,但它是根据我告诉它不要这样做的列进行排序的。我想先按第 3 列按优先级排序,然后按第 4 列、第 5 列、第 6 列进行排序。这是怎么回事?

这是我的代码:sort -n -s -t ',' -k3,6

这是我的输入:

a1,b1,2,15,50,ABBA    
a1,a1,2,26,55,ABBA    
a11,2a1,2,33,55,ABBA   
b1,a1,2,80,99,ABA   
c2,a1,3,20,40,CAN   
a1,b2,3,51,300,CAN   
a3,a3,4,1000,2000,ART   
d3,c3,4,1700,2050,ART   
d3,c2c,4,1600,2050,ART   
b1,a3,4,1800,2051,ART   

这是我当前的输出:

a1,b1,2,15,50,ABBA   
a1,a1,2,26,55,ABBA   
a11,2a1,2,33,55,ABBA   
b1,a1,2,80,99,ABA   
c2,a1,3,20,40,CAN   
a1,b2,3,51,300,CAN   
a3,a3,4,1000,2000,ART   
d3,c3,4,1700,2050,ART 
d3,c2c,4,1600,2050,ART
b1,a3,4,1800,2051,ART   

但我想要的和预期的输出应该是:

a1,b1,2,15,50,ABBA   
a1,a1,2,26,55,ABBA   
a11,2a1,2,33,55,ABBA   
b1,a1,2,80,99,ABA   
c2,a1,3,20,40,CAN   
a1,b2,3,51,300,CAN   
a3,a3,4,1000,2000,ART   
d3,c2c,4,1600,2050,ART    
d3,c3,4,1700,2050,ART
b1,a3,4,1800,2051,ART 

我正在使用Linux。

答案1

问题是您的排序键是包含逗号的字符串。

当比较其中两个键时,例如4,1700,2050,ART4,1600,2050,ART,它们比较平等的因为(在您的语言环境中)只有键的第一部分可以转换为数值(4 和 4)。

要解决此问题,请分别将每个字段与该字段的正确类型(数字或非数字)进行比较:

sort -s -t, -k3,3n -k4,4n -k5,5n -k6,6 file

大多数实现都sort提供了一个--debug对于检测此类问题非常有帮助的选项。在我的 FreeBSD 系统上,这清楚地表明您的原始命令在比较我提到的字段时存在问题:

$ sort --debug -n -s -t ',' -k3,6 file
[...]
; k1=<4,1000,2000,ART   >, k2=<4,1700,2050,ART   >; s1=<a3,a3,4,1000,2000,ART   >, s2=<d3,c3,4,1700,2050,ART   >; cmp1=0
; k1=<4,1700,2050,ART   >, k2=<4,1600,2050,ART   >; s1=<d3,c3,4,1700,2050,ART   >, s2=<d3,c2c,4,1600,2050,ART   >; cmp1=0
; k1=<4,1600,2050,ART   >, k2=<4,1800,2051,ART   >; s1=<d3,c2c,4,1600,2050,ART   >, s2=<b1,a3,4,1800,2051,ART   >; cmp1=0
[...]

cmp1=0表明键k1k2比较相等。

作为比较:

$ sort --debug -s -t, -k3,3n -k4,4n -k5,5n -k6,6 file
[...]
; k1=<4>, k2=<4>; k1=<1000>, k2=<1700>; s1=<a3,a3,4,1000,2000,ART   >, s2=<d3,c3,4,1700,2050,ART   >; cmp1=-1
; k1=<4>, k2=<4>; k1=<1700>, k2=<1600>; s1=<d3,c3,4,1700,2050,ART   >, s2=<d3,c2c,4,1600,2050,ART   >; cmp1=1
; k1=<4>, k2=<4>; k1=<1000>, k2=<1600>; s1=<a3,a3,4,1000,2000,ART   >, s2=<d3,c2c,4,1600,2050,ART   >; cmp1=-1
; k1=<4>, k2=<4>; k1=<1700>, k2=<1800>; s1=<d3,c3,4,1700,2050,ART   >, s2=<b1,a3,4,1800,2051,ART   >; cmp1=-1
[...]

GNUsort可能会以完全不同的格式生成调试输出。

答案2

问题在于您是按词汇排序而不是按数字排序。您需要-n按数字排序,否则100将在123甚至之前排序2

$ printf '2\n123\n100\n' | sort
100
123
2

但是,随着-n

$ printf '2\n123\n100\n' | sort -n
2
100
123

因此,在您的情况下,您需要将 添加到n要按数字排序的字段:

$ sort -t, -k3n,6n file  
a1,b1,2,15,50,ABBA    
a1,a1,2,26,55,ABBA    
a11,2a1,2,33,55,ABBA   
b1,a1,2,80,99,ABA   
c2,a1,3,20,40,CAN   
a1,b2,3,51,300,CAN   
a3,a3,4,1000,2000,ART   
d3,c2c,4,1600,2050,ART   
d3,c3,4,1700,2050,ART   
b1,a3,4,1800,2051,ART   

相关内容