2012-07-12 184 views
5

我需要与UNIX排序一些数据进行排序,但我不完全正确的语法,数据的模样UNIX排序为2场数字顺序

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 

但我不打扰第一个排序

+0

当我尝试你给你的样本数据的命令行,它产生的答案你说你想... – jacobm 2012-07-12 01:42:21

+0

@jacobm,重新检查第3列,它的排序错误 – Steve 2012-07-12 01:45:50

+0

我在solaris 10,如果这有所作为,是啊第三列仍然不正确 – jdex 2012-07-12 01:48:30

回答

2

关于重新设计Unix sort('工作分类例程构建中的理论和实践',JP Linderman,AT & T Bell Labs Tech Journal,Oct 1984),有一篇非常吸引人的文章,这不幸的是,它不能在互联网上使用,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,再次给出原始行。

+0

有关的其他方式? http://cs.fit.edu/~pkc/classes/writing/samples/bentley93engineering.pdf – 2012-07-12 23:20:27

+0

@FrankComputer:相关的,绝对 - 它引用了Linderman。但不是一回事。另请参阅[为快速排序选择数据透视表](http://stackoverflow.com/questions/164163/choosing-a-pivot-for-quicksort/164183#164183),其中提到了您所询问的宾利纸,以及一些其他。 – 2012-07-12 23:40:26

+0

能够在这里得到一个简短的预览:http://books.google.com/books?id=Hy62AAAAIAAJ&q=Linderman#search_anchor – 2012-07-12 23:54:25

2

挣扎到现在排序第3列步骤数如何将Step:转换成sort,然后再转换回来?我相信这可以让你要寻找的结果:(只需使用cat这里说明的目的如果只是一个普通的文件,那么它可以被传递到第一sed

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' 

+0

我一直希望只使用排序的整洁的解决方案,但我想这也可以。 +1会看到其他人是否知道与 – jdex 2012-07-12 03:30:40

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: 

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

此解决方案由Step字段暂时'.'使得所有排序字段可以用相同的字符('.')分离后更换空白空间。排序完成后,'.'将被替换为空白。

+0

它没有按步骤列排序虽然.. – jdex 2012-07-12 03:31:28

+0

@jdex我找到了一个我相信的解决方案,请查看这是否是您的问题的可接受答案。 – Levon 2012-07-12 11:50:03

+0

+ 1,我真的很想避免修改数据,因为我提供的不是完整的数据集。每个步骤都有一个字符串描述(有时也包含“Step”)。它开始看起来像没有其他方式虽然 – jdex 2012-07-13 00:05:05

2

这可能会为你工作:

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

还是很玄乎:按步骤

  • sort -nst. -k1,1 -k2,2 -k3,3各种

    1. sort -k3,3n类:

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

      第一种使用两类由主要数字,但保持步骤或明镜

    第二个作品,但只有在第3主号码仍低于100

    或者是:

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

    我认为第一个可以工作,但是我在solaris 10上使用的排序版本没有-s选项。 – jdex 2012-07-12 23:34:50

    +0

    @jdex对不起,我猜'-s'是一个GNU功能。 'sed'解决方案可能会有所帮助 – potong 2012-07-13 00:00:28