使用Unix排序对多个键进行排序


137

我有可能需要按1-n键排序的大文件。其中一些键可能是数字键,有些则可能不是数字键。这是一个固定宽度的柱状文件,因此没有定界符。

有没有一种很好的方法可以用Unix排序呢?使用一个键,就像使用“ -n”一样简单。我已经阅读了手册页并简要搜索了Google,但没有找到一个很好的例子。我将如何实现这一目标?

注意:由于文件大小可能,我排除了Perl。这将是不得已的办法。


一到两行示例数据对于创建示例命令行非常有帮助。另外,“ 1-n”键是否意味着您需要按可变数量的键排序?不用脚本就能做到这一点很有趣……
Ken Gentle

我在sort命令周围有一个PHP包装器,以启用1-n功能。
克里斯·克洛伯丹兹

Answers:


69

使用-k选项(或--key=POS1[,POS2])。它可以出现多次,并且每个键可以具有全局选项(例如n用于数字排序)


7
在排序手册页上:“ POS是F [.C] [OPTS],其中F是字段编号,C是字段中的字符位置;两者都是源1。” 有关完整文档,请参见手册页。
亚当·罗森菲尔德

49
如果您不想发疯,也请参阅安德拉斯的答案。
罗恩

1
以上两个评论都是准确和可加的。谢谢先生们
Ken Gentle

314

不过请注意:

如果要主要按字段3排序文件,然后按字段2排序文件,则需要这样做:

sort -k 3,3 -k 2,2 < inputfile

不是这样的: sort -k 3 -k 2 < inputfile它按照从字段3的开始到行尾的字符串对文件进行排序(可能是唯一的)。

-k, --key=POS1[,POS2]     start a key at POS1 (origin 1), end it at POS2
                          (default end of line)

8
生活在改变。谢谢。
davidtbernal 2014年

2
哎呀!现在我必须修复一个脚本,因为之前我只看到上面的第一个答案...好事我还没有依赖于脚本输出....
Wildcard

真好!现在,如果我要对字段3进行数字排序和反向排序,而对字段2进行非数字排序和正常(升序)排序怎么办?:)
阿伦(Arun)

2
手册页末尾说明了@Arun POS。您只需将订购选项附加到字段号上,如下所示:sort -k 3,3nr -k 2,2
andras

1
啊 什么是违反直觉的界面:-k2应该是-k2,2和后面的逗号-k2,应该是“线或任何神奇的默认结束”。
android.weasel

94

-k选项就是您想要的。

-k 1.4,1.5n -k 1.14,1.15n

将在第一个字段中使用字符位置4-5(固定宽度都是一个字段),并将其作为第一个键进行数字排序。

第二个键也是第一个字段中的字符14-15。

(编辑)

示例(我所拥有的都是DOS / cygwin方便的):

dir | \cygwin\bin\sort.exe -k 1.4,1.5n -k 1.40,1.60r

对于数据:

12/10/2008  01:10 PM         1,564,990 outfile.txt

对目录列表按月号(pos 4-5)进行数字排序,然后按文件名(pos 40-60)反向排序。由于没有选项卡,因此所有字段都是要排序的。


如果输入数据中没有空格,则只有一个字段。但是,您的示例很有用。
乔纳森·勒夫勒

纠正:如果输入数据中没有/ tabs /。在DOS的“ dir”命令输出中,没有选项卡。
克林顿·皮尔斯

有关如何使用选项(数字,反向)的示例非常有帮助,因为几乎不可能仅从手册页中找到如何使用方法,而其他答案都没有提及。我希望我可以为此加2。;)
msb13年

22

这是一种按数字和字典顺序对csv文件中的各个列进行排序的方法,第5列及其后按字典顺序进行排序

~/test>sort -t, -k1,1n -k2,2n -k3,3d -k4,4n -k5d  sort.csv
1,10,b,22,Ga
2,2,b,20,F
2,2,b,22,Ga
2,2,c,19,Ga
2,2,c,19,Gb,hi
2,2,c,19,Gb,hj
2,3,a,9,C

~/test>cat sort.csv
2,3,a,9,C
2,2,b,20,F
2,2,c,19,Gb,hj
2,2,c,19,Gb,hi
2,2,c,19,Ga
2,2,b,22,Ga
1,10,b,22,Ga

请注意,-k1,1n表示从第1列开始到第1列结束的数字。如果我在下面做了操作,它将把第1列和第2列连接起来,使1,10排序为110

~/test>sort -t, -k1,2n -k3,3 -k4,4n -k5d  sort.csv
2,2,b,20,F
2,2,b,22,Ga
2,2,c,19,Ga
2,2,c,19,Gb,hi
2,2,c,19,Gb,hj
2,3,a,9,C
1,10,b,22,Ga

1
这是最佳答案,因为它显示了如何对不同的列使用不同的开关
xaxa

12

我相信您的情况

sort -t@ -k1.1,1.4 -k1.5,1.7 ... <inputfile

会更好地工作。@是字段分隔符,请确保它是一个无处出现的字符。那么您的输入将被视为由一列组成。

编辑:显然clintp已经给出了类似的答案,对不起。正如他指出的那样,可以将标志“ n”和“ r”添加到每个-k ....选项中。


即使gnu.org/software/coreutils/manual/html_node/…的默认分隔符是空格,有时字段数也不是您所期望的。也许因为LC_CTYPE语言环境设置,其他人在这里说过。如有疑问,请从行的开头算起!
Brad Dre

5

注意,可能还希望通过-s开关来稳定排序,以便等排名的行也保持其在输出中的原始相对顺序。


2

我只想添加一些技巧,当您使用sort时,请注意影响键比较顺序的语言环境。我通常会显式地使用LC_ALL = C使我想要的语言环境成为可能。


LC_ALL = C也会导致相当大的加速!
mat kelcey
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.