分类
这个 分类 程序对标准输入或命令行指定的一个或多个文件的内容进行排序,并将结果发送到标准输出。 使用我们使用的相同技术 猫,我们可以演示直接从键盘处理标准输入:
[我@linuxbox ~]$ 排序> foo.txt
工商银行
[我@linuxbox ~]$ 猫 foo.txt
abc
[我@linuxbox ~]$ 排序> foo.txt
工商银行
[我@linuxbox ~]$ 猫 foo.txt
abc
输入命令后,我们输入字母“c”、“b”和“a”,然后再次输入 Ctrl-d 表示文件结束。 然后我们查看生成的文件,看到这些行现在按排序顺序出现。
建立 分类 可以在命令行上接受多个文件作为参数,可以 合并 多个文件合并为一个排序的整体。 例如,如果我们有三个文本文件并想将它们组合成一个单独的排序文件,我们可以这样做:
排序 file1.txt file2.txt file3.txt > final_sorted_list.txt
排序 file1.txt file2.txt file3.txt > final_sorted_list.txt
sort 有几个有趣的选项。 以下是部分清单:
表 20-1:常用排序选项
附加选项 | 多头期权 | 描述 |
-b | --忽略前导空白 | 默认情况下,排序是在 |
整条线,从 | ||
行中的第一个字符。 这个 | ||
选项导致排序忽略 | ||
行中的前导空格和 | ||
根据第一个计算排序 | ||
上的非空白字符 | ||
线。 | ||
-f | --忽略大小写 | 使排序不区分大小写。 |
-n | --数字排序 | 根据字符串的数值计算执行排序。 使用此选项允许对数字值而不是字母值执行排序。 |
-r | - 逆转 | 倒序排列。 结果在 |
下降而不是上升 | ||
秩序。 | ||
-k | --键=field1[,field2] | 根据定位的关键字段排序 |
, field1 至 field2 而不是 | ||
整条线。 见下面的讨论。 | ||
-m | - 合并 | 将每个参数视为名称 |
预排序的文件。 合并多个 | ||
文件到一个单一的排序结果 | ||
无需执行任何额外操作 | ||
排序。 | ||
-o | --输出=文件 | 将排序的输出发送到 文件 宁 |
比标准输出。 | ||
-t | --字段分隔符=坦克 | 定义字段分隔符 |
特点。 默认字段是 | ||
由空格或制表符分隔。 |
尽管上面的大多数选项都是不言自明的,但有些不是。 首先,让我们看看 -n 选项,用于数字排序。 使用此选项,可以根据数值对值进行排序。 我们可以通过对结果进行排序来证明这一点 du 命令确定磁盘空间的最大用户。 通常情况下, du 命令按路径名顺序列出摘要的结果:
[我@linuxbox ~]$ du -s /usr/share/* | 头
第252话
96 /usr/share/acpi-支持
8 /usr/共享/添加用户
第196话
第344话
8 /usr/share/alsa-base 12488 /usr/share/anthy
8 /usr/共享/apmd
21440 /usr/share/应用安装
48 /usr/share/应用程序注册表
[我@linuxbox ~]$ du -s /usr/share/* | 头
第252话
96 /usr/share/acpi-支持
8 /usr/共享/添加用户
第196话
第344话
8 /usr/share/alsa-base 12488 /usr/share/anthy
8 /usr/共享/apmd
21440 /usr/share/应用安装
48 /usr/share/应用程序注册表
在这个例子中,我们将结果通过管道传输到 头 将结果限制在前十行。 我们可以生成一个按数字排序的列表,以这种方式显示十个最大的空间消费者:
[我@linuxbox ~]$ du -s /usr/share/* | 排序-nr | 头
509940 /usr/share/语言环境-langpack
242660 /usr/共享/文档
197560 /usr/share/字体
179144 /usr/共享/gnome
146764 /usr/共享/myspell
144304 /usr/共享/gimp
135880 /usr/共享/字典
76508 /usr/共享/图标
68072 /usr/共享/应用程序
62844 /usr/共享/foomatic
[我@linuxbox ~]$ du -s /usr/share/* | 排序-nr | 头
509940 /usr/share/语言环境-langpack
242660 /usr/共享/文档
197560 /usr/share/字体
179144 /usr/共享/gnome
146764 /usr/共享/myspell
144304 /usr/共享/gimp
135880 /usr/共享/字典
76508 /usr/共享/图标
68072 /usr/共享/应用程序
62844 /usr/共享/foomatic
通过使用 -nr 选项,我们生成反向数字排序,最大值首先出现在结果中。 这种排序有效,因为数值出现在每行的开头。 但是,如果我们想根据在该行中找到的某个值对列表进行排序,该怎么办? 例如,一个结果 ls -l:
[我@linuxbox ~]$ ls -l /usr/bin | 头
总152948
-rwxr-xr-x | 1 | 根 | 根 | 34824 | 2016-04-04 | 02:42 | [ |
-rwxr-xr-x | 1 | 根 | 根 | 101556 | 2007-11-27 | 06:08 | a2p |
-rwxr-xr-x | 1 | 根 | 根 | 13036 | 2016-02-27 | 08:22 | 连接 |
-rwxr-xr-x | 1 | 根 | 根 | 10552 | 2007-08-15 | 10:34 | ACPI |
-rwxr-xr-x | 1 | 根 | 根 | 3800 | 2016-04-14 | 03:51 | acpi_fakekey |
-rwxr-xr-x | 1 | 根 | 根 | 7536 | 2016-04-19 | 00:19 | acpi_监听 |
-rwxr-xr-x | 1 | 根 | 根 | 3576 | 2016-04-29 | 07:57 | 添加部分 |
-rwxr-xr-x | 1 | 根 | 根 | 20808 | 2016-01-03 | 18:02 | 地址线 |
-rwxr-xr-x | 1 | 根 | 根 | 489704 | 2016-10-09 | 17:02 | 熟练的批处理 |
暂时忽略, ls 可以按大小对其结果进行排序,我们可以使用 分类 也可以按文件大小对此列表进行排序:
[我@linuxbox ~]$ ls -l /usr/bin | 排序 -nr -k 5 | 头
-rwxr-xr-x | 1 | 根 | 根 | 8234216 | 2016-04-07 | 17:42 | Inkscape中 |
-rwxr-xr-x | 1 | 根 | 根 | 8222692 | 2016-04-07 | 17:42 | 墨观 |
-rwxr-xr-x | 1 | 根 | 根 | 3746508 | 2016-03-07 | 23:45 | gimp-2.4 |
-rwxr-xr-x | 1 | 根 | 根 | 3654020 | 2016-08-26 | 16:16 | 量子 |
-rwxr-xr-x | 1 | 根 | 根 | 2928760 | 2016-09-10 | 14:31 | gdbtui |
-rwxr-xr-x | 1 | 根 | 根 | 2928756 | 2016-09-10 | 14:31 | GDB |
-rwxr-xr-x | 1 | 根 | 根 | 2602236 | 2016-10-10 | 12:56 | 净 |
-rwxr-xr-x | 1 | 根 | 根 | 2304684 | 2016-10-10 | 12:56 | rpc客户端 |
-rwxr-xr-x | 1 | 根 | 根 | 2241832 | 2016-04-04 | 05:56 | 能力倾向 |
-rwxr-xr-x | 1 | 根 | 根 | 2202476 | 2016-10-10 | 12:56 | smbcacls |
许多用途 分类 涉及处理 表格数据,比如结果 ls 上面的命令。 如果我们将数据库术语应用于上表,我们会说每一行都是一个 记录 并且每条记录包含多个 领域,例如文件属性、链接数、文件名、文件大小等。 分类 能够处理单个字段。 在数据库术语中,我们能够指定一个或多个 关键领域 用作 排序键. 在上面的例子中,我们指定 n 和 r 执行反向数字排序和指定的选项 -k 5 生产 分类 使用第五个字段作为排序的键。
这个 k 选项很有趣,有很多功能,但首先我们需要谈谈如何 分类 定义字段。 让我们考虑一个非常简单的文本文件,其中包含一行包含作者姓名的内容:
威廉·肖茨
威廉·肖茨
默认情况下, 分类 将此行视为有两个字段。 第一个字段包含以下字符:
“威廉”
第二个字段包含字符:
“镜头”
这意味着空白字符(空格和制表符)用作字段之间的分隔符,并且在执行排序时将分隔符包含在字段中。
再看看我们的一行 ls 输出,我们可以看到一行包含八个字段,第五个字段是文件大小:
-rwxr-xr-x 1 根 8234216 2016-04-07 17:42inkscape
-rwxr-xr-x 1 根 8234216 2016-04-07 17:42inkscape
对于我们接下来的一系列实验,让我们考虑以下文件,其中包含从 2006 年到 2008 年发布的三个流行 Linux 发行版的历史。文件中的每一行都有三个字段:发行版名称、版本号和 MM/DD 中的发行日期/YYYY 格式:
SUSE | 10.2 | 12/07/2006 |
Fedora | 10 | 11/25/2008 |
SUSE | 11.0 | 06/19/2008 |
Ubuntu | 8.04 | 04/24/2008 |
Fedora | 8 | 11/08/2007 |
SUSE | 10.3 | 10/04/2007 |
Ubuntu | 6.10 | 10/26/2006 |
Fedora | 7 | 05/31/2007 |
Ubuntu | 7.10 | 10/18/2007 |
Ubuntu | 7.04 | 04/19/2007 |
SUSE | 10.1 | 05/11/2006 |
Fedora | 6 | 10/24/2006 |
Fedora | 9 | 05/13/2008 |
Ubuntu | 6.06 | 06/01/2006 |
Ubuntu | 8.10 | 10/30/2008 |
Fedora | 5 | 03/20/2006 |
使用文本编辑器(也许 VIM),我们将输入这些数据并命名生成的文件 发行版.txt.
接下来,我们将尝试对文件进行排序并观察结果:
[我@linuxbox | ~]$ | 排序发行版.txt |
Fedora 10 | 11/25/2008 | |
Fedora 5 | 03/20/2006 | |
Fedora 6 | 10/24/2006 | |
Fedora 7 | 05/31/2007 | |
Fedora 8 | 11/08/2007 | |
Fedora 9 | 05/13/2008 | |
苏斯 10.1 | 05/11/2006 | |
苏斯 10.2 | 12/07/2006 | |
苏斯 10.3 | 10/04/2007 | |
苏斯 11.0 | 06/19/2008 | |
Ubuntu的6.06 | 06/01/2006 | |
Ubuntu的6.10 | 10/26/2006 | |
Ubuntu的7.04 | 04/19/2007 | |
Ubuntu的7.10 | 10/18/2007 | |
Ubuntu的8.04 | 04/24/2008 | |
Ubuntu的8.10 | 10/30/2008 |
嗯,它主要是有效的。 问题出现在 Fedora 版本号的排序中。 由于“1”在字符集中出现在“5”之前,因此版本“10”最终位于顶部,而版本“9”则位于底部。
为了解决这个问题,我们将不得不对多个键进行排序。 我们想对第一个字段执行字母排序,然后对第二个字段执行数字排序。 分类 允许
的多个实例 -k 选项,以便可以指定多个排序键。 事实上,一个键可能包括一系列字段。 如果没有指定范围(就像我们之前的例子一样), 分类 使用以指定字段开始并延伸到行尾的键。 这是我们的多键排序的语法:
[我@linuxbox | ~]$ | 排序 --key=1,1 --key=2n distros.txt |
Fedora 5 | 03/20/2006 | |
Fedora 6 | 10/24/2006 | |
Fedora 7 | 05/31/2007 | |
Fedora 8 | 11/08/2007 | |
Fedora 9 | 05/13/2008 | |
Fedora 10 | 11/25/2008 | |
苏斯 10.1 | 05/11/2006 | |
苏斯 10.2 | 12/07/2006 | |
苏斯 10.3 | 10/04/2007 | |
苏斯 11.0 | 06/19/2008 | |
Ubuntu的6.06 | 06/01/2006 | |
Ubuntu的6.10 | 10/26/2006 | |
Ubuntu的7.04 | 04/19/2007 | |
Ubuntu的7.10 | 10/18/2007 | |
Ubuntu的8.04 | 04/24/2008 | |
Ubuntu的8.10 | 10/30/2008 |
虽然为了清楚起见我们使用了选项的长形式, -k 1,1 -k 2n 将完全等效。 在 key 选项的第一个实例中,我们指定了要包含在第一个键中的字段范围。 由于我们想将排序限制在第一个字段,因此我们指定 1,1 意思是“从第一场开始,到第一场结束”。 在第二种情况下,我们指定 2n,这意味着字段 2 是排序键,并且排序应该是数字。 可以在键说明符的末尾包含一个选项字母,以指示要执行的排序类型。 这些选项字母与全局选项相同 分类 程序: b (忽略前导空格), n (数字排序), r (反向排序)等。
我们列表中的第三个字段包含一个不方便排序的日期格式。 在计算机上,日期通常采用 YYYY-MM-DD 格式,以便于按时间顺序排序,但我们采用的是美式格式 MM/DD/YYYY。 我们如何按时间顺序对这个列表进行排序?
幸好, 分类 提供了一种方法。 关键选项允许指定 抵消 在字段内,所以我们可以在字段内定义键:
[我@linuxbox ~]$ 排序 -k 3.7nbr -k 3.1nbr -k 3.4nbr distros.txt
Fedora 10 11 年 25 月 2008 日
Ubuntu 8.10 10 年 30 月 2008 日
[我@linuxbox ~]$ 排序 -k 3.7nbr -k 3.1nbr -k 3.4nbr distros.txt
Fedora 10 11 年 25 月 2008 日
Ubuntu 8.10 10 年 30 月 2008 日
SUSE | 11.0 | 06/19/2008 |
Fedora | 9 | 05/13/2008 |
Ubuntu | 8.04 | 04/24/2008 |
Fedora | 8 | 11/08/2007 |
Ubuntu | 7.10 | 10/18/2007 |
SUSE | 10.3 | 10/04/2007 |
Fedora | 7 | 05/31/2007 |
Ubuntu | 7.04 | 04/19/2007 |
SUSE | 10.2 | 12/07/2006 |
Ubuntu | 6.10 | 10/26/2006 |
Fedora | 6 | 10/24/2006 |
Ubuntu | 6.06 | 06/01/2006 |
SUSE | 10.1 | 05/11/2006 |
Fedora | 5 | 03/20/2006 |
通过指定 -k 3.7 我们指导 分类 使用从第三个字段中的第七个字符开始的排序键,对应于年份的开始。 同样,我们指定 -k 3.1 和 -k 3.4 隔离日期的月和日部分。 我们还添加了 n 和 r 选项来实现反向数字排序。 这 b 包含选项以抑制日期字段中的前导空格(其数字因行而异,从而影响排序的结果)。
有些文件不使用制表符和空格作为字段分隔符; 例如, / etc / passwd文件
文件:
[我@linuxbox ~]$ 头 /etc/passwd root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/bin/sh bin:x:2:2:bin:/bin:/bin/sh sys:x:3:3:sys:/dev:/bin/sh sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/bin/sh man:x:6:12:man:/var/cache/man:/bin/sh lp:x:7:7:lp:/var/spool/lpd:/bin/sh mail:x:8:8:mail:/var/mail:/bin/sh news:x:9:9:news:/var/spool/news:/bin/sh
[我@linuxbox ~]$ 头 /etc/passwd root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/bin/sh bin:x:2:2:bin:/bin:/bin/sh sys:x:3:3:sys:/dev:/bin/sh sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/bin/sh man:x:6:12:man:/var/cache/man:/bin/sh lp:x:7:7:lp:/var/spool/lpd:/bin/sh mail:x:8:8:mail:/var/mail:/bin/sh news:x:9:9:news:/var/spool/news:/bin/sh
此文件中的字段以冒号 (:),那么我们将如何使用关键字段对该文件进行排序? 分类 提供 -t 用于定义字段分隔符的选项。 排序 passwd文件 文件在第七个字段(帐户的默认外壳),我们可以这样做:
[我@linuxbox ~]$ sort -t ':' -k 7 /etc/passwd | 头
我:x:1001:1001:我自己,,,:/home/me:/bin/bash
[我@linuxbox ~]$ sort -t ':' -k 7 /etc/passwd | 头
我:x:1001:1001:我自己,,,:/home/me:/bin/bash
root:x:0:0:root:/root:/bin/bash dhcp:x:101:102::/不存在:/bin/false
gdm:x:106:114:Gnome 显示管理器:/var/lib/gdm:/bin/false hplip:x:104:7:HPLIP 系统用户,,,:/var/run/hplip:/bin/false klog :x:103:104::/home/klog:/bin/false messagebus:x:108:119::/var/run/dbus:/bin/false polkituser:x:110:122:PolicyKit,,,: /var/run/PolicyKit:/bin/false 脉冲:x:107:116:PulseAudio 守护进程,,,:/var/run/pulse:/bin/false
root:x:0:0:root:/root:/bin/bash dhcp:x:101:102::/不存在:/bin/false
gdm:x:106:114:Gnome 显示管理器:/var/lib/gdm:/bin/false hplip:x:104:7:HPLIP 系统用户,,,:/var/run/hplip:/bin/false klog :x:103:104::/home/klog:/bin/false messagebus:x:108:119::/var/run/dbus:/bin/false polkituser:x:110:122:PolicyKit,,,: /var/run/PolicyKit:/bin/false 脉冲:x:107:116:PulseAudio 守护进程,,,:/var/run/pulse:/bin/false
通过指定冒号字符作为字段分隔符,我们可以对第七个字段进行排序。