5

我需要用 unix sort 对一些数据进行排序,但我无法准确地计算出正确的语法,数据看起来像

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

4 回答 4

2

Stepand:在途中转换为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。)

于 2012-07-12T01:57:26.960 回答
2

有一篇关于重新设计 Unix 的引人入胜的文章sort('Theory and Practice in the Construction of a Working Sort Routine',JP Linderman,AT&T Bell Labs Tech Journal,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,并再次返回原始行。

于 2012-07-12T02:32:12.760 回答
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按主要数字排序,但保持步序

第二个有效,但前提是第三个主要数字保持在 100 以下。

也许:

sed 's/ /./2' file | sort -nt. -k1,1 -k2,2 -k3,3 -k4,4 | sed 's/\./ /3'
于 2012-07-12T04:02:55.657 回答
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此解决方案通过将字段后的空格临时替换为 a '.',以便所有排序字段可以用相同的字符 ( '.') 分隔。排序完成后,'.'再次用空白替换。

于 2012-07-12T03:10:23.573 回答