按“所有字段”字典顺序排序

按“所有字段”字典顺序排序

这是一个非常简单(尽管是人为的)示例来说明问题。假设我有一个文件/tmp/table,其中包含以下内容:

px9xc
px12xc
pqx12xc
pqx9xc

在这里,x角色是一个字段分隔符。因此,该文件包含一个 4 行 3 列的表。 (此后,我将这些列称为“字段”。)

我想根据字段按字典顺序对该表进行排序。我的意思是,如果两行在字段 1 中具有相同的值,则通过根据字段 2 排序来打破平局,如果字段 2 中的值也相同,则根据字段 3 排序。1 注意:之内每个字段,我们假设sort的默认顺序。

这意味着,对于 中的表/tmp/table,所需的排序是

px12xc
px9xc
pqx12xc
pqx9xc

(请注意,在sort默认顺序中,12位于之前9。)

简单的调用sort不会产生所需的排序,因为字段分隔符不会被解释为这样:

% sort /tmp/table
pqx12xc
pqx9xc
px12xc
px9xc

这也无法产生所需的排序:

% sort -tx -k1,3 /tmp/table
pqx12xc
pqx9xc
px12xc
px9xc

sort我发现使用(至少是我的系统上安装的,即 GNU 的)实现所需排序的唯一方法是:

% sort -tx -k1,1 -k2,2 -k3,3 /tmp/table
px12xc
px9xc
pqx12xc
pqx9xc

此解决方案的问题(除了指定与字段一样多的选项的乏味之外-k?,?)是它不能推广到具有不同字段数量的表。

是否有一种方便的方法(无论是否sort)将基于字段的字典顺序应用于“所有字段”?


1更一般地说,如果表中有字段,要决定两行中哪一行按字典顺序排在第一位,可以应用以下递归规则,让k范围从 1 到:如果两行的字段 1 到 的值相同k - 1,然后根据中的值打破平局k第-个字段。

答案1

我们可以欺骗并用另一个允许“本机”排序工作的分隔符(例如 NUL 字符)替换分隔符,然后将其设置回来。

例如

tr x '\000' < file.txt | sort | tr '\000' x

现在我们可能需要注意区域设置对排序的影响,因此您可能需要这样做

tr x '\000' < file.txt | LANG=C sort | tr '\000' x

仅当数据中不包含 NUL 时,此方法才有效!

使用格式化表格可以更轻松地解释其工作原理:

我们需要比较两行:

ab  | def
abc | def

我们将分隔符设置为 NUL 并与 进行ab<NUL>def比较abc<NUL>def。出现<NUL>在前面c,因此我们已经对第一个字段进行了正确排序。

现在假设第一个字段匹配,第二个字段不同

abc | def
abc | ghi

现在我们比较abc<NUL>def一下abc<NUL>ghi。我们通过第一个字段和分隔符获得了匹配,现在正在对第二个字段进行排序。

相关内容