使用“ sort”命令按列优先级对CSV文件进行排序


91

我有一个csv文件,我想按列优先级对其进行排序,例如“ order by”。例如:

3;1;2
1;3;2
1;2;3
2;3;1
2;1;3
3;2;1

如果这种情况是“选择”的结果,则“ order by”将如下所示:order by column2,column1,column3-结果将是:

2;1;3
3;1;2
1;2;3
3;2;1
1;3;2
2;3;1

我想知道如何在Unix上使用“ sort”命令获得相同的结果。


4
顺便说一句,这是一个ssv文件(用分号分隔的值):P
John Strood

Answers:


153
sort --field-separator=';' --key=2,1,3

8
如果值是数字,那么您可能要考虑使用-n“根据字符串数值比较”的-g选项或“根据通用数值比较”的选项。数值的字符串比较将获得数字顺序,如1,10,2,20。至少这些是我在CentOS上的版本上可用的选项。您应该在手册页上确认排序版本上的正确选项。
亚当·波拉德

4
我明白了sort: stray character in field spec: invalid field specification ‘2,1,3’
Martin Thoma 2014年

3
但是,sort --field-separator=',' -r -k3 -k1 -k2 source.csv > target.csv为我工作。
马丁·托马

6
@MartinThoma已经很长时间了,但我遇到了您的问题,发现了sort --field-separator=';' --key={2,1,3}。这工作于GNU coreutils 8.42016
mrbolichi '18年

2
@mrbolichi这种表示法--key={2,1,3}使用bash的括号扩展
kvantour

28

假设你有另一行3;10;3中的unsorted.csv文件。然后,我猜您期望得到一个数字排序的结果:

2;1;3
3;1;2
1;2;3
3;2;1
1;3;2
2;3;1
3;10;3

而不是按字母顺序排序的:

2;1;3
3;1;2
3;10;3
1;2;3
3;2;1
1;3;2
2;3;1

为此,您必须使用-n

sort --field-separator=';' -n -k 2,2 -k 1,1 -k 3,3 unsorted.csv

值得一提的是2,2必须使用。如果仅2使用,则将sort字符串从字段2的开头到结尾。2,2确保仅使用字段2


7
关于-k 2和-k 2,2之间差异的指针很重要!我在初次阅读手册页时就忽略了这一点。谢谢。
usonianhorizo​​n '16

我增加了一些额外的行3;10;33:10:53:10;23;10;3在源文件中的顺序,并在使用只是 -k 2,2它似乎排序列2和3的手册页说"The -k option may be specified multiple times, in which case subsequent keys are compared when earlier keys compare equal."。就我而言,较早的键(值= 10)确实比较相等,但是,我没有-k多次指定。我不确定这是否可靠,还是与我的系统(mac)有关。最终,只要基本排序正确,就没有关系。
达沃斯

哦,我看到还有一种-s稳定的排序方法,它忽略了等号键,根据男人的说法,这显然更快。
达沃斯

24

上面查理的答案在Cygwin(排序版本2.0,GNU textutils)上对我不起作用,以下代码对我有效:

sort -t"," -k2 -k1 -k1

3
Cygwin具有较旧的版本。与往常一样,手册页是您的朋友。
查理·马丁

2
我同意@CharlieMartin的观点,您应该检查系统上的手册页。在CentOS上,我使用了sort --field-separator=';' -k2 -k1 -k3 test.csv
Adam Porad

-6

..并且如果有人遵循“排序”解决方案,但现在希望获得的不仅仅是每行唯一的唯一条目(即,唯一条目的前X个),那么使用“排序”对文件进行排序后,就可以使用我在这里创建的一个小应用程序:

https://github.com/danieliversen/MiscStuff/blob/master/scripts/findTopUniques.java


2
对你有好处!但是在您的情况下,您可能只使用了cat unsorted-file | sort | uniq | head -X-when X是您希望输出的第一行的数量。
斯拉维克·梅尔瑟

@SlavikMe非常感谢您的评论!但是,您的建议会得出不同的结果。您的建议会在完全排序的文件中获得前X行,而我们希望获得每个“键”的前X行(即,如果您有一个带名称的CSV,则如果您对它进行排序通过第2列“姓”,那么您的命令可能只会获得3行,其中“ Allen”作为姓,而我们的命令将获得“ Allen”,“ Brittain”,“ Charles”等)。不过谢谢!
Daniel Iversen

6
你错了。我建议您在评论之前尝试一下我编写的命令。请注意,uniqsort和之间有一个管道顺序的命令,该命令在head提取顶部行之前为所有排序的行提供唯一性。
Slavik Meltser
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.