我正在尝试对多个列进行排序。结果与预期不符。

这是我的数据(people.txt):

Simon Strange 62
Pete Brown 37
Mark Brown 46
Stefan Heinz 52
Tony Bedford 50
John Strange 51
Fred Bloggs 22
James Bedford 21
Emily Bedford 18
Ana Villamor 44
Alice Villamor 50
Francis Chepstow 56


以下内容正常工作:

bash-3.2$ sort -k2 -k3 <people.txt                                                                                                                    
Emily Bedford 18                                                                                                                                      
James Bedford 21                                                                                                                                      
Tony Bedford 50                                                                                                                                       
Fred Bloggs 22                                                                                                                                        
Pete Brown 37                                                                                                                                         
Mark Brown 46                                                                                                                                         
Francis Chepstow 56                                                                                                                                   
Stefan Heinz 52                                                                                                                                       
John Strange 51                                                                                                                                       
Simon Strange 62                                                                                                                                      
Ana Villamor 44                                                                                                                                       
Alice Villamor 50


但是,以下内容无法按预期工作:

bash-3.2$ sort -k2 -k1 <people.txt                                        
Emily Bedford 18                                                                                                                                      
James Bedford 21                                                                                                                                      
Tony Bedford 50                                                                                                                                       
Fred Bloggs 22                                                                                                                                        
Pete Brown 37                                                                                                                                         
Mark Brown 46                                                                                                                                         
Francis Chepstow 56                                                                                                                                   
Stefan Heinz 52                                                                                                                                       
John Strange 51                                                                                                                                       
Simon Strange 62                                                                                                                                      
Ana Villamor 44                                                                                                                                       
Alice Villamor 50


我试图按姓氏排序,然后按名,但您会看到Villamors的顺序不正确。我希望按姓氏排序,然后在匹配姓氏时按姓氏排序。

似乎有一些我不了解的方法。我当然可以使用另一种方式(使用awk)来执行此操作,但是我想了解排序。

我正在Mac OS X上使用标准的Bash shell。

#1 楼

-k2这样的关键规范意味着要考虑从2到行尾的所有字段。因此,Villamor 44Villamor 50之前结束。由于这两个不相等,因此sort -k2 -k1中的第一个比较足以区分这两行,而第二个排序键-k1不被调用。如果两个Villamors的年龄相同,则-k1会使它们按名字进行排序。

要按单个列进行排序,请使用-k2,2作为关键规格。这意味着要使用从#2到#2的字段,即仅使用第二个字段。

sort -k2 -k3 <people.txt是多余的:等效于sort -k2 <people.txt。要按姓氏,名字,年龄排序,请运行以下命令:

sort -k2,2 -k1,1 <people.txt


或等效地sort -k2,2 -k1 <people.txt,因为只有这三个字段且分隔符是相同。实际上,从sort -k2,2 <people.txt可以得到相同的效果,因为当一行子集中的所有键都相同时,sort将整行用作最后的选择。

还请注意,默认字段分隔符为非空白和空白之间的过渡,因此键将包含前导空白(在您的示例中,对于第一行,第一个键将为"Emily",而第二个键为" Bedford"。添加-b选项以剥离这些空白:

sort -b -k2,2 -k1,1


也可以在每个键的基础上通过在键启动规范的末尾添加b标志来实现:

sort -k2b,2 -k1,1 <people.txt


但要记住一点:只要在密钥规范中添加一个这样的标志,全局标志(例如-n-r ...)就不再适用于它们,因此更好避免将每个按键标志和全局标志混在一起。

评论


你钉了我假设(做一件危险的事)指定-k1表示使用字段1,其中该字段在默认字段分隔符(空格)处结束。但是,正如您明确指出的那样,k选项期望您指定键的起点和终点,它们可以是也可以不是单个字段。您的解决方案运行完美,更重要的是,我很清楚为什么这样做。非常感谢。

–哈里
2012年10月26日在7:40

这是巨大的。关于KEYDEF的许多其他资料都谈到了-k1 -k2,却没有强调COMMA在格式上的重要性,以限制在每个排序步骤中考虑哪些列。我被困了好几个小时才找到答案。手册页在这里令人困惑。它没有解释用逗号表示法指定的“开始和停止”位置。谢谢!

–詹森·罗勒(Jason Rohrer)
19-10-3在4:07

抱歉,是否需要重定向?可以直接对文件进行排序吗?像sort -n ...文件

–han独奏
19年11月11日在13:48

@hansolo是的,也可以。

–吉尔斯'所以-不再是邪恶的'
19年11月11日23:29

@ Gilles'SO-stopbeingevil'是的,我只是在帖子中看到所有人无缘无故地重定向到标准输入。这就是为什么:)也很好的答案,我不确定如何限制该列以进行比较

–han独奏
19年11月12日在5:03



#2 楼

使用GNU sort时,您是这样进行的,不确定MacOS:

sort -k2,2 -k1 <people.txt


根据评论进行更新。引用自man sort

   -k, --key=KEYDEF
          sort via a key; KEYDEF gives location and type

   KEYDEF is F[.C][OPTS][,F[.C][OPTS]] for start and stop position, where
   F is a field number and C a character position in the field; both are
   origin 1, and the stop position defaults to the line's end.


评论


您能解释一下这种奇怪的表示法吗?

–scai
2012年10月24日12:19

这让我沿着正确的方向思考-谢谢。但是,您不必为第二个-k指定停止点。那是-k2,2 -k1,1,否则停止点被当作行的结尾?

–哈里
2012年10月26日7:45

@TonyBedford,正确。但是未指定停止位置不会更改当前输入的结果,但会强制一致性,以防万一您有多行具有相同字段2和1的行。因此,我宁愿允许最后一个-k包含尽可能多的行能够。

–manatwork
2012年10月26日8:01



@manatwork没必要;如果所有指定的字段比较均等,sort将比较整行。或者使用GNU排序,您可以使用-s进行稳定排序。

–augustar
15年3月2日在19:08