unix排序为2个字段的数字顺序

时间:2012-07-12 01:16:04

标签: bash unix sorting sed awk

我需要使用unix排序对某些数据进行排序,但我无法确切地说出正确的语法,数据看起来像

3.9.1 Step 10:
3.9.1 Step 20:
3.8.10 Step 20:
3.10.2 Step 10:
3.8.4 Step 90:
3.8.4 Step 100:
3.8.4 Step 10:

我想首先使用主要号码,然后是步骤号码,例如,上面排序的数据看起来像。

3.8.4 Step 10:
3.8.4 Step 90:
3.8.4 Step 100:
3.8.10 Step 20:
3.9.1 Step 10:
3.9.1 Step 20:
3.10.2 Step 10:

我找到了按此网站上第一个数字排序的方法:

sort -t. -k 1,1n -k 2,2n -k 3,3n

但是我现在很难按第3列步骤编号排序而不会打扰第一种

4 个答案:

答案 0 :(得分:2)

如何将Step:转换为sort,然后转换回去?我相信这会得到您正在寻找的结果:

cat your-file.txt \
    | sed -e 's/ Step \(.*\):$/.\1/g' \
    | sort -t. -k1,1n -k2,2n -k3,3n -k4,4n \
    | sed -e 's/\(.*\)\.\(.*\)$/\1 Step \2:/g'

(这里只是使用cat用于说明目的。如果它只是一个普通文件,那么它可以传递给第一个sed。)

答案 1 :(得分:2)

有一篇关于重新设计Unix sort('构建工作分类例程的理论与实践',JP Linderman,AT& T贝尔实验室技术期刊,1984年10月)的一篇引人入胜的文章,不幸的是,可以在互联网上找到,AFAICT(我看了一年左右,但没有找到它;我刚看了一眼,可以找到它的参考,但不是文章本身)。除此之外,文章还证明了对于Unix sort,比较时间远远超过了移动数据的成本(当您考虑比较必须比较每行确定的字段时,并不是非常令人惊讶,但移动'数据'是只是一个切换指针的问题)。其中一个结果就是他们建议做danfuzz建议的事情;映射键使比较变得容易。他们表明,即使是简单的脚本解决方案也可以节省时间,而排序工作真的很难。

因此,您可以考虑使用不太可能自然地出现在数据文件中的字符(例如 Control-A )作为关键字段分隔符。

sed 's/^\([^.]*\)[.]\([^.]*\)[.]\([^ ]*\) Step \([0-9]*\):.*/\1^A\2^A\3^A\4^A&/' file |
sort -t'^A' -k1,1n -k2,2n -k3,3n -k4,4n |
sed 's/^.*^A//'

第一个命令是硬命令。它标识4个数字字段,并输出它们由所选字符分隔(上面写为^A,键入为 Control-A ),然后输出原始行的副本。排序然后以数字方式对前四个字段起作用,最后的sed命令剥离每行的前面,包括最后一个 Control-A ,为您提供原始行试。

答案 2 :(得分:2)

这可能对您有用:

 sort -k3,3n file | sort -nst. -k1,1 -k2,2 -k3,3

或非常不确定:

 sort -nt. -k1,1 -k2,2 -k3,3 -k3.7 file

第一种使用两种:

  1. sort -k3,3n按步骤排序
  2. sort -nst. -k1,1 -k2,2 -k3,3按主要数字排序,但保留步骤顺序
  3. 第二种方法有效但仅在第三主要数字仍然低于100时才有效。

    或者也许:

    sed 's/ /./2' file | sort -nt. -k1,1 -k2,2 -k3,3 -k4,4 | sed 's/\./ /3'
    

答案 3 :(得分:1)

修订版

这将生成您指定的输出:

sed 's/Step /Step./' data|sort -t. -n -k1,1 -k2,2 -k3,3 -k4|sed 's/Step./Step /'

结果:

3.8.4 Step 10:
3.8.4 Step 90:
3.8.4 Step 100:
3.8.10 Step 20:
3.9.1 Step 10:
3.9.1 Step 20:
3.10.2 Step 10:

这种挑战是排序字段由'.'(对于版本号)和默认空格(对于步骤编号)定义。您不能为同一排序命令指定多个/不同的字段分隔符。将几种类型与不同的字段分隔符组合在一起并没有产生正确的输出。

此解决方案的工作原理是将Step字段暂时后的空格替换为'.',以便所有排序字段可以用相同的字符分隔({{1 }})。排序完成后,'.'将再次替换为空白。