使用命令行中的 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 上使用以减少键入)来定义要按哪个字段排序。例如,要按每行的第二个字段(从 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 选项混淆,后者是 --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 (未验证)

好例子

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