使用命令行 sort 命令进行排序

使用 sort 命令,直接从 Linux、BSD 或 Mac 终端中以您认为有意义的格式重新组织您的数据。
225 位读者喜欢这篇文章。
Coding on a computer

如果您曾经使用过电子表格应用程序,那么您就知道行可以按列的内容排序。例如,如果您有一个费用列表,您可能希望按日期、升序价格或类别等对其进行排序。如果您习惯使用终端,您可能不想仅仅为了排序文本数据而使用大型办公应用程序。而这正是 sort 命令的用途。

安装

您无需安装 sort,因为它总是包含在任何 POSIX 系统中。在大多数 Linux 系统上,sort 命令捆绑在 GNU 组织的实用程序集合中。在其他 POSIX 系统(如 BSD 和 Mac)上,默认的 sort 命令不是来自 GNU,因此某些选项可能有所不同。我将尝试在本文中说明 GNU 和 BSD 的实现。

按字母顺序排序行

默认情况下,sort 命令查看文件中每行的第一个字符,并按升序字母顺序输出每行。如果多行上的两个字符相同,则它会考虑下一个字符。例如

$ cat distro.list
Slackware
Fedora
Red Hat Enterprise Linux
Ubuntu
Arch
1337
Mint
Mageia
Debian
$ sort distro.list
1337
Arch
Debian
Fedora
Mageia
Mint
Red Hat Enterprise Linux
Slackware
Ubuntu

使用 sort 不会更改原始文件。Sort 是一个过滤器,因此如果您想以排序形式保留数据,则必须使用 >tee 重定向输出

$ sort distro.list | tee distro.sorted
1337
Arch
Debian
[...]
$ cat distro.sorted
1337
Arch
Debian
[...]

按列排序

复杂的数据集有时需要按每行的第一个字母以外的其他内容排序。例如,想象一下动物列表,以及每种动物的物种和属,并且每个“字段”(电子表格中的“单元格”)都由可预测的分隔符字符定义。这是电子表格导出的一种常见数据格式,以至于存在 CSV(逗号分隔值)文件扩展名来标识此类文件(尽管 CSV 文件不必是逗号分隔的,分隔文件也不必使用 CSV 扩展名才是有效且可用的)。考虑以下示例数据集

Aptenodytes;forsteri;Miller,JF;1778;Emperor
Pygoscelis;papua;Wagler;1832;Gentoo
Eudyptula;minor;Bonaparte;1867;Little Blue
Spheniscus;demersus;Brisson;1760;African
Megadyptes;antipodes;Milne-Edwards;1880;Yellow-eyed
Eudyptes;chrysocome;Viellot;1816;Southern Rockhopper
Torvaldis;linux;Ewing,L;1996;Tux

给定此示例数据集,您可以使用 --field-separator 选项(在 BSD 和 Mac 上使用 -t,或在 GNU 上使用以减少键入)将分隔符字符设置为分号(因为此示例使用分号而不是逗号,但它可以使用任何字符),并使用 --key 选项(BSD 和 Mac 上为 -k,或 GNU 上为 -k 以减少键入)来定义要按哪个字段排序。例如,要按每行的第二个字段(从 1 开始,而不是 0)排序

sort --field-separator=";" --key=2
Megadyptes;antipodes;Milne-Edwards;1880;Yellow-eyed
Eudyptes;chrysocome;Viellot;1816;Sothern Rockhopper
Spheniscus;demersus;Brisson;1760;African
Aptenodytes;forsteri;Miller,JF;1778;Emperor
Torvaldis;linux;Ewing,L;1996;Tux
Eudyptula;minor;Bonaparte;1867;Little Blue
Pygoscelis;papua;Wagler;1832;Gentoo

这有点难以阅读,但 Unix 以其构造命令的管道方法而闻名,因此您可以使用 column 命令来“美化”输出。使用 GNU column

$ sort --field-separator=";" \
--key=2 penguins.list | \
column --table --separator ";"
Megadyptes   antipodes   Milne-Edwards  1880  Yellow-eyed
Eudyptes     chrysocome  Viellot        1816  Southern Rockhopper
Spheniscus   demersus    Brisson        1760  African
Aptenodytes  forsteri    Miller,JF      1778  Emperor
Torvaldis    linux       Ewing,L        1996  Tux
Eudyptula    minor       Bonaparte      1867  Little Blue
Pygoscelis   papua       Wagler         1832  Gentoo

对于新用户来说稍微有点神秘(但键入起来更短),BSD 和 Mac 上的命令选项

$ sort -t ";" \
-k2 penguins.list | column -t -s ";"
Megadyptes   antipodes   Milne-Edwards  1880  Yellow-eyed
Eudyptes     chrysocome  Viellot        1816  Southern Rockhopper
Spheniscus   demersus    Brisson        1760  African
Aptenodytes  forsteri    Miller,JF      1778  Emperor
Torvaldis    linux       Ewing,L        1996  Tux
Eudyptula    minor       Bonaparte      1867  Little Blue
Pygoscelis   papua       Wagler         1832  Gentoo

key 定义不必设置为 2。任何现有字段都可以用作排序键。

反向排序

您可以使用 --reverse 选项(BSD 或 Mac 或 GNU 上为 -r,为了简洁起见)反转排序列表的顺序

$ sort --reverse alphabet.list
z
y
x
w
[...]

您可以通过将正常排序的输出通过 tac 管道传输来实现相同的结果。

按月份排序(仅限 GNU)

在一个完美的世界中,每个人都会按照 ISO 8601 标准编写日期:年、月、日。这是一种指定唯一日期的逻辑方法,并且计算机很容易理解。然而,人们经常使用其他方法来识别日期,包括带有相当任意名称的月份。

幸运的是,GNU sort 命令考虑到了这一点,并且能够按月份名称正确排序。使用 --month-sort (-M) 选项

$ cat month.list
November
October
September
April
[...]
$ sort --month-sort month.list
January
February
March
April
May
[...]
November
December

月份可以通过全名或其名称的某些部分来识别。

人类可读的数字排序(仅限 GNU)

人类和计算机之间另一个常见的混淆点是数字组。例如,人类经常将“1024 千字节”写成“1KB”,因为对于人脑来说,解析“1KB”比“1024”更容易、更快捷(并且数字越大,就越容易)。但是,对于计算机而言,诸如 9KB 之类的字符串大于例如 1MB(即使 9KB 仅为兆字节的一小部分)。GNU sort 命令提供了 --human-numeric-sort (-h) 选项来帮助正确解析这些值。

$ cat sizes.list
2M
12MB
1k
9k
900
7000
$ sort --human-numeric-sort
900
7000
1k
9k
2M
12MB

存在一些不一致之处。例如,16,000 字节大于 1KB,但 sort 无法识别到这一点

$ cat sizes0.list
2M
12MB
16000
1k
$ sort -h sizes0.list
16000
1k
2M
12MB

从逻辑上讲,在这种情况下,16,000 应该写成 16KB,因此 GNU sort 并非完全应该受到责备。只要您确定您的数字是一致的,--human-numeric-sort 就可以帮助以计算机友好的方式解析人类可读的数字。

随机排序(仅限 GNU)

有时,实用程序会提供执行与其预期用途相反的操作的选项。在某种程度上,对于 sort 命令来说,拥有随机“排序”文件的能力是没有意义的。但是,该命令的工作流程使其成为一项方便的功能。您可以使用不同的命令,例如 shuf,或者您只需将一个选项添加到您正在使用的命令中即可。无论它是臃肿还是巧妙的 UX 设计,GNU sort 命令都提供了任意排序文件的方法。

最纯粹的任意排序形式是 --random-sort-R 选项(不要与 -r 选项混淆,-r 选项是 --reverse 的简写)。

$ sort --random-sort alphabet.list
d
m
p
a
[...]

您可以对文件运行多次随机排序,每次都会得到不同的结果。

已排序

GNU 和 BSD sort 命令还有许多其他可用功能,因此请花一些时间了解这些选项。您会惊讶于 sort 的灵活性,尤其是在它与其他 Unix 实用程序结合使用时。

接下来阅读什么
标签
Seth Kenlon
Seth Kenlon 是一位 UNIX 极客、自由文化倡导者、独立多媒体艺术家和 D&D 爱好者。他曾在电影和计算行业工作,并且经常同时从事这两个行业。

7 条评论

我认为另一个重要的选项是 -f 标志,或 --ignore-case。如果没有它,您将按 ASCII 值排序,其中所有大写字母都在小写字母之前。

我从未读过如此有效和独特的内容!保持更新……

从未?这话说得够分量。

很高兴您喜欢这篇文章的独特内容,Subhash!

回复 ,作者 Subhash Shastri

很棒的例子。从没听说过“column”命令。谢谢!

我也花了很长时间才发现它,但当您需要它时,它非常方便。

感谢阅读!

回复 ,作者 PioNie (未验证)

好例子

知识共享许可协议本作品根据知识共享署名-相同方式共享 4.0 国际许可协议获得许可。
© . All rights reserved.