我需要使用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列步骤编号排序而不会打扰第一种
答案 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
第一种使用两种:
sort -k3,3n
按步骤排序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'
答案 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 }})。排序完成后,'.'
将再次替换为空白。