Bash Shell IP地址排序

Bash Shell IP地址排序,你想对数字 IP 地址列表进行排序,但希望按最后部分的数字或在逻辑上按整个地址进行排序。

解决方案

按照最后一部分数字排序(旧语法)。

$ sort -t. -n +3.0 ipaddr.list
10.0.0.2
192.168.0.2
192.168.0.4
10.0.0.5
192.168.0.12
10.0.0.20
$

按照整个 IP 地址排序(POSIX 语法)。

$ sort -t . -k 1,1n -k 2,2n -k 3,3n -k 4,4n ipaddr.list
10.0.0.2
10.0.0.5
10.0.0.20
192.168.0.2
192.168.0.4
192.168.0.12
$

讨论

我们知道这些数据都是数值,因此使用了 -n 选项。-t 选项用于指定字段之间的分隔符(这里的分隔符是点号),这样就可以指定先按照哪个字段排序了。在第一个例子中,我们在左边找到第 3 个字段(从 0 开始计数),从该字段的第 1 个字符(也是从 0 开始计数)开始排序,写作 +3.0。

在第二个例子中,我们没有再沿用传统的(已经过时)+pos1 -pos2 格式,而是采用了新的 POSIX 语法规范。与旧格式不同,在 POSIX 语法中,字段是从 1 开始计数的。

sort -t . -k 1,1n -k 2,2n -k 3,3n -k 4,4n ipaddr.list

哇,真难看。以下是旧格式,也没好到哪去。

sort -t. +0n -1 +1n -2 +2n -3 +3n -4

两者都用 -t. 来定义字符分隔符,但指定排序字段时就大不一样了。在 POSIX 语法中,-k 1,1n 的意思是“排序起止范围从第一个字段(1)开头至(,)第一个字段(1)末尾,按照数值排序(n)”。只要搞明白这部分的写法,剩下的就很简单了。如果使用多个排序字段,重要的是一定要告诉 sort 字段的结束位置。默认是直到行尾才结束,但这通常并不符合我们的要求,要是你不明白这一点,着实会摸不着头脑。

sort 使用的排序方法受到语言环境设置的影响。如果得到的结果与预期不符,你可以检查一下这方面的设置。

排序结果在不同系统上会出现不一致的情况,这取决于 sort 命令是否默认使用了稳定排序。如果排序字段内容相同,那么稳定排序会在排序结果中保留其原始顺序。

Linux 和 Solaris 默认没有使用稳定排序,而 NetBSD 使用了稳定排序。-S 选项在 NetBSD 上用于关闭稳定排序,但在其他 sort 版本中,该选项用于设置缓冲区大小。

假设我们有一个普通文件:

10.0.0.4        # mainframe
192.168.0.12    # speedy
10.0.0.20       # lanyard
192.168.0.4     # office
10.0.0.2        # sluggish
192.168.0.2     # laptop

如果在 Linux 或 Solaris 系统上执行下列命令:

sort -t. -k4n ipaddr.list

或者在 NetBSD 系统上执行下列命令:

sort -t. -S -k4n ipaddr.list

我们得到排序后的结果如下表中第一列所示。去掉 NetBSD 系统中的 sort 命令的 -S 选项后,结果如表中第二列所示。

Linux/Solaris/NetBSD系统上的排序结果比对
Bash Shell IP地址排序

在输入文件 ipaddr.list 中,以 192.168 开头的地址最先出现,接着是 10 开头的地址,如果出现平局(tie),也就是两个排序字段的值一样,那么稳定排序会将 192.168 开头的地址放在排序结果的前面。在 上表 中,我们可以看到 laptop 和 sluggish 就是这种情况,因为两者的第四个字段都是 2;mainframe 和 office 也是同理,两者的第四个字段都是 4。在 Linux 的默认排序(以及指定了 -S 选项的 NetBSD)中,无法确保排序结果是稳定的。

要想追求简单实用,可以按照 IP 地址列表中的文本排序。这一次我们选用 # 字符作为分隔符,并按照字母顺序对第二个字段排序,得到的结果如下所示。

$ sort -t'#' -k2 ipaddr.list
10.0.0.20       # lanyard
192.168.0.2     # laptop
10.0.0.5        # mainframe
192.168.0.4     # office
10.0.0.2        # sluggish
192.168.0.12    # speedy
$

排序范围从第二个字段开始,直到行尾。因为每行仅有一个分隔符(#),所以不必指定范围的结束位置,不过你也可以写成 -k2,2

酷客网相关文章:

赞(0)

评论 抢沙发

评论前必须登录!