标签 sort 下的文章

在 Linux、BSD 或 Mac 的终端中使用 sort 命令,按自己的需求重新整理数据。

如果你曾经用过数据表应用程序,你就会知道可以按列的内容对行进行排序。例如,如果你有一个费用列表,你可能希望对它们进行按日期或价格升序抑或按类别进行排序。如果你熟悉终端的使用,你不会仅为了排序文本数据就去使用庞大的办公软件。这正是 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(以逗号分隔的数据comma-separated values)后缀可以标识这些文件(虽然 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 上也可以用简写 -t )设置分隔符为分号(因为该示例数据中是用分号而不是逗号,理论上分隔符可以是任意字符),用 --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

当然 -k 不一定非要设为 2。任意存在的字段都可以被设为排序的键。

逆序排列

你可以用 --reverse(BSD/Mac 上用 -r,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 kilobytes” 写成 “1KB”,因为人类解析 “1 KB” 比 “1024” 要容易且更快(数字越大,这种差异越明显)。对于计算机来说,一个 9 KB 的字符串要比诸如 1 MB 的字符串大(尽管 9 KB 是 1 MB 很小一部分)。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

有一些情况例外。例如,“16000 bytes” 比 “1 KB” 大,但是 sort 识别不了。

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

逻辑上来说,这个示例中 16000 应该写成 16 KB,所以也不应该全部归咎于GNU sort。只要你确保数字的一致性,--human-numeric-sort 可以用一种计算机友好的方式解析成人类可读的数字。

随机排序(仅 GNU 支持)

有时候工具也提供了一些与设计初衷相悖的选项。某种程度上说,sort 命令提供对一个文件进行随机排序的能力没有任何意义。这个命令的工作流让这个特性变得很方便。你可以用其他的命令,像 shuf ,或者你可以用现在的命令添加一个选项。不管你认为它是一个臃肿的还是极具创造力的用户体验设计,GNU sort 命令提供了对文件进行随机排序的功能。

最纯粹的随机排序格式选项是 --random-sort-R(不要跟 -r 混淆,-r--reverse 的简写)。

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

每次对文件运行随机排序都会有不同的结果。

结语

GNU 和 BSD 的 sort 命令还有很多功能,所以花点时间去了解这些选项。你会惊异于 sort 的灵活性,尤其是当它和其他的 Unix 工具一起使用时。


via: https://opensource.com/article/19/10/get-sorted-sort

作者:Seth Kenlon 选题:lujun9972 译者:lxbwolf 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

上一篇文章里,我们已经探讨了关于sort命令的多个例子,如果你错过了这篇文章,可以点击下面的链接进行阅读。今天的这篇文章作为上一篇文章的继续,将讨论关于sort命令的剩余用法,与上一篇一起作为Linux ‘sort’命令的完整指南。

在我们继续深入之前,先创建一个文本文档‘month.txt’,并且将上一次给出的数据填进去。

$ echo -e "mar\ndec\noct\nsep\nfeb\naug" > month.txt
$ cat month.txt

Populate Content

15、 通过使用’M‘选项,对’month.txt‘文件按照月份顺序进行排序。

$ sort -M month.txt

注意:‘sort’命令需要至少3个字符来确认月份名称。

Sort File Content by Month in Linux

16、 把数据整理成方便人们阅读的形式,比如1K、2M、3G、2T,这里面的K、G、M、T代表千、兆、吉、梯。 (LCTT 译注:此处命令有误,ls 命令应该增加 -h 参数,径改之)

$ ls -lh /home/$USER | sort -h -k5

Sort Content Human Readable Format

17、 在上一篇文章中,我们在例子4中创建了一个名为‘sorted.txt’的文件,在例子6中创建了一个‘lsl.txt’。‘sorted.txt'已经排好序了而’lsl.txt‘还没有。让我们使用sort命令来检查两个文件是否已经排好序。

$ sort -c sorted.txt

Check File is Sorted

如果它返回0,则表示文件已经排好序。

$ sort -c lsl.txt

Check File Sorted Status

报告无序。存在矛盾……

18、 如果文字之间的分隔符是空格,sort命令自动地将空格后的东西当做一个新文字单元,如果分隔符不是空格呢?

考虑这样一个文本文件,里面的内容可以由除了空格之外的任何符号分隔,比如‘|’,‘\’,‘+’,‘.’等……

创建一个分隔符为+的文本文件。使用‘cat‘命令查看文件内容。

$ echo -e "21+linux+server+production\n11+debian+RedHat+CentOS\n131+Apache+Mysql+PHP\n7+Shell Scripting+python+perl\n111+postfix+exim+sendmail" > delimiter.txt

$ cat delimiter.txt

Check File Content by Delimiter

现在基于由数字组成的第一个域来进行排序。

$ sort -t '+' -nk1 delimiter.txt

Sort File By Fields

然后再基于非数字的第四个域排序。

Sort Content By Non Numeric

如果分隔符是制表符,你需要在’+‘的位置上用$’\t’代替,如上例所示。

19、 对主用户目录下使用‘ls -l’命令得到的结果基于第五列(‘文件大小’)进行一个乱序排列。

$ ls -l /home/avi/ | sort -k5 -R 

Sort Content by Column in Random Order

每一次你运行上面的脚本,你得到结果可能都不一样,因为结果是随机生成的。

正如我在上一篇文章中提到的规则2所说——sort命令会将以小写字母开始的行排在大写字母开始的行前面。看一下上一篇文章的例3,字符串‘laptop’在‘LAPTOP’前出现。

20、 如何覆盖默认的排序优先权?在这之前我们需要先将环境变量LC\_ALL的值设置为C。在命令行提示栏中运行下面的代码。

$ export LC_ALL=C

然后以非默认优先权的方式对‘tecmint.txt’文件重新排序。

$ sort tecmint.txt

Override Sorting Preferences

覆盖排序优先权

不要忘记与example 3中得到的输出结果做比较,并且你可以使用‘-f’,又叫‘-ignore-case’(忽略大小写)的选项来获取更有序的输出。

$ sort -f tecmint.txt

Compare Sorting Preferences

21、 给两个输入文件进行‘sort‘,然后把它们连接成一行!

我们创建两个文本文档’file1.txt‘以及’file2.txt‘,并用数据填充,如下所示,并用’cat‘命令查看文件的内容。

$ echo -e “5 Reliable\n2 Fast\n3 Secure\n1 open-source\n4 customizable” > file1.txt
$ cat file1.txt

Populate Content with Numbers

用如下数据填充’file2.txt‘。

$ echo -e “3 RedHat\n1 Debian\n5 Ubuntu\n2 Kali\n4 Fedora” > file2.txt
$ cat file2.txt

Populate File with Data

现在我们对两个文件进行排序并连接。

$ join <(sort -n file1.txt) <(sort file2.txt)

Sort Join Two Files

我所要讲的全部内容就在这里了,希望与各位保持联系,也希望各位经常来逛逛。有反馈就在下面评论吧。


via: http://www.tecmint.com/linux-sort-command-examples/

作者:Avishek Kumar 译者:DongShuaike 校对:wxy

本文由 LCTT 原创翻译,Linux中国 荣誉推出

Sort是用于对单个或多个文本文件内容进行排序的Linux程序。Sort命令以空格作为字段分隔符,将一行分割为多个关键字对文件进行排序。需要注意的是除非你将输出重定向到文件中,否则Sort命令并不对文件内容进行实际的排序(即文件内容没有修改),只是将文件内容按有序输出。

本文的目标是通过14个实际的范例让你更深刻的理解如何在Linux中使用sort命令。

1、 首先我们将会创建一个用于执行‘sort’命令的文本文件(tecmint.txt)。工作路径是‘/home/$USER/Desktop/tecmint’。

下面命令中的‘-e’选项将启用‘\’转义,将‘\n’解析成换行

$ echo -e "computer\nmouse\nLAPTOP\ndata\nRedHat\nlaptop\ndebian\nlaptop" > tecmint.txt

Split String by Lines in Linux

2、 在开始学习‘sort’命令前,我们先看看文件的内容及其显示方式。

$ cat tecmint.txt

Check Content of File

3、 现在,使用如下命令对文件内容进行排序。

$ sort tecmint.txt

Sort Content of File linux

注意:上面的命令并不对文件内容进行实际的排序,仅仅是将其内容按有序方式输出。

4、 对文件‘tecmint.txt’文件内容排序,并将排序后的内容输出到名为sorted.txt的文件中,然后使用cat命令查看验证sorted.txt文件的内容。

$ sort tecmint.txt > sorted.txt
$ cat sorted.txt

Sort File Content in Linux

5、 现在使用‘-r’参数对‘tecmint.txt’文件内容进行逆序排序,并将输出内容重定向到‘reversesorted.txt’文件中,并使用cat命令查看文件的内容。

$ sort -r tecmint.txt > reversesorted.txt
$ cat reversesorted.txt

Sort Content By Reverse

6、 创建一个新文件(lsl.txt),文件内容为在home目录下执行‘ls -l’命令的输出。

$ ls -l /home/$USER > /home/$USER/Desktop/tecmint/lsl.txt
$ cat lsl.txt

Populate Output of Home Directory

我们将会看到对其他字段进行排序的例子,而不是对默认的开始字符进行排序。

7、 基于第二列(符号连接的数量)对文件‘lsl.txt’进行排序。

$ sort -nk2 lsl.txt

注意:上面例子中的‘-n’参数表示对数值内容进行排序。当想基于文件中的数值列对文件进行排序时,必须要使用‘-n’参数。

Sort Content by Column

8、 基于第9列(文件和目录的名称,非数值)对文件‘lsl.txt’进行排序。

$ sort -k9 lsl.txt

Sort Content Based on Column

9、 sort命令并非仅能对文件进行排序,我们还可以通过管道将命令的输出内容重定向到sort命令中。

$ ls -l /home/$USER | sort -nk5

Sort Content Using Pipe Option

10、 对文件tecmint.txt进行排序,并删除重复的行。然后检查重复的行是否已经删除了。

$ cat tecmint.txt
$ sort -u tecmint.txt

Sort and Remove Duplicates

目前我们发现的排序规则:

除非指定了‘-r’参数,否则排序的优先级按下面规则排序

  • 以数字开头的行优先级最高
  • 以小写字母开头的行优先级次之
  • 待排序内容按字典序进行排序
  • 默认情况下,‘sort’命令将带排序内容的每行关键字当作一个字符串进行字典序排序(数字优先级最高,参看规则 1)

11、 在当前位置创建第三个文件‘lsla.txt’,其内容用‘ls -lA’命令的输出内容填充。

$ ls -lA /home/$USER > /home/$USER/Desktop/tecmint/lsla.txt
$ cat lsla.txt

Populate Output With Hidden Files

了解ls命令的读者都知道‘ls -lA’ 等于 ‘ls -l’ + 隐藏文件,所以这两个文件的大部分内容都是相同的。

12、 对上面两个文件内容进行排序输出。

$ sort lsl.txt lsla.txt

Sort Contents of Two Files

注意文件和目录的重复

13、 现在我们看看怎样对两个文件进行排序、合并,并且删除重复行。

$ sort -u lsl.txt lsla.txt

Sort, Merge and Remove Duplicates from File

此时,我们注意到重复的行已经被删除了,我们可以将输出内容重定向到文件中。

14、 我们同样可以基于多列对文件内容进行排序。基于第2,5(数值)和9(非数值)列对‘ls -l’命令的输出进行排序。

$ ls -l /home/$USER | sort -t "," -nk2,5 -k9

Sort Content By Field Column

先到此为止了,在接下来的文章中我们将会学习到‘sort’命令更多的详细例子。届时敬请关注我们。保持分享精神。若喜欢本文,敬请将本文分享给你的朋友。


via: http://www.tecmint.com/sort-command-linux/

作者:Avishek Kumar 译者:cvsher 校对:wxy

本文由 LCTT 原创翻译,Linux中国 荣誉推出