如何使用不同的字段分隔符对多个字段进行排序

时间:2013-06-06 06:23:41

标签: unix sorting

我想在多个字段和多个字段分隔符上对文件进行排序。请帮忙。这是我的示例数据文件:

$ cat Data3
My Text|50002/100/43
My Message|50001/100/7
Help Text|50001/100/7
Help Message|50002/100/11
Text Message|50001/100/63
Visible Text|50001/100/52
Invisible Text|50002/100/1

第一个字段分隔符是管道符号,第二个字段分隔符是/。我想首先在第二个字段上对此数据进行排序,然后在其中,数据应按最后一个字段的排序顺序排序(由/分隔)。最后,我的排序数据应如下所示:

Help Text|50001/100/7
My Message|50001/100/7
Visible Text|50001/100/52
Text Message|50001/100/63
Invisible Text|50002/100/1
Help Message|50002/100/11
My Text|50002/100/43

通过使用sort -k2,2n -t'|',我可以对字段2(50001/50002)进行排序,但是在该值内,我如何对最后一个字段进行排序(由/分隔)?

4 个答案:

答案 0 :(得分:11)

此数据集最简单的技巧是将第二列视为版本号。

$ cat Data3 | sort -k2,2V -t'|'
Help Text|50001/100/7
My Message|50001/100/7
Visible Text|50001/100/52
Text Message|50001/100/63
Invisible Text|50002/100/1
Help Message|50002/100/11
My Text|50002/100/43

但是,根据您的输入,这并不总是有效。这将起作用,因为第二列中的值是相同的。

您可以执行fedorqui建议的操作并运行两次排序,第二次执行稳定排序。从联机帮助页: - s, - stable(通过禁用最后的比较来稳定排序)

首先对二级排序标准进行排序。然后执行稳定排序,这将保持排序顺序在与主排序条件共享相同密钥的行中。

$ cat Data3 | sort -k3,3n -t'/' | sort -k2,2n -t'|' -s
Help Text|50001/100/7
My Message|50001/100/7
Visible Text|50001/100/52
Text Message|50001/100/63
Invisible Text|50002/100/1
Help Message|50002/100/11
My Text|50002/100/43

在这种情况下你有点幸运,因为-k2,2n -t'|'将第二列“50001/100/7”视为一个数字,它可能是50001.如果用逗号分隔而不是斜杠并且您在环境中使用不同的语言环境,则可能会出现奇怪的情况。例如,在我的环境中默认运行en_US.UTF-8,其行为与此类似。

$ cat Data3 | tr '/' ',' | sort -k3,3n -t',' | LC_NUMERIC=en_US.UTF-8 sort -k2,2n -t'|' -s
Help Text|50001,100,7
My Message|50001,100,7
Invisible Text|50002,100,1
Visible Text|50001,100,52
Text Message|50001,100,63
Help Message|50002,100,11
My Text|50002,100,43

您期望的是:

$ cat Data3 | tr '/' ',' | sort -k3,3n -t',' | LC_NUMERIC=C sort -k2,2n -t'|' -s
Help Text|50001,100,7
My Message|50001,100,7
Visible Text|50001,100,52
Text Message|50001,100,63
Invisible Text|50002,100,1
Help Message|50002,100,11
My Text|50002,100,43

答案 1 :(得分:4)

只要文本中没有其他'|'字符,以下代码就适用于我。

tr '|' '/' | sort -n -t '/' -k3 -k4 | sed -re 's/^([^/]*)\/(.*)$/\1|\2/'

答案 2 :(得分:3)

使用awk

的小技巧
$ cat Data3  | awk -F'[|/]' '{print $2"\t"$4"\t"$0}' | sort -k1 -k2 -n | cut -f3-
Help Text|50001/100/7
My Message|50001/100/7
Visible Text|50001/100/52
Text Message|50001/100/63
Invisible Text|50002/100/1
Help Message|50002/100/11
My Text|50002/100/43
  • 您可以awk使用指定的所有分隔符-F'[|/]'首先打印排序键$2"\t"$4,然后打印输入行$0
  • 然后使用多个密钥sort执行一个-k1 -k2(注意:与-k1,2不同)
  • 然后cut返回输入行

适用于许多场景

答案 3 :(得分:2)

你可以使用这个(低效但简单)的脚本:

#!/usr/bin/perl
print sort  {   @ka = split ?[|/]?, $a;
                @kb = split ?[|/]?, $b;
                $ka[1] <=> $kb[1]
             || $ka[3] <=> $kb[3]
             || $ka[0] cmp $kb[0]
            } <>

如果您不关心具有相同值的行,则可以省略行|| $ka[0] cmp $kb[0]