基于不在固定位置的字段对文件进行排序

时间:2017-06-08 02:53:29

标签: linux sorting unix

我是unix排序的新手。 我有一组数据......例行: 当我尝试sort -n命令时,它给了我这个: 它从0_0开始,第二个是10_0,我怎么能让它从0_0开始然后跟随1_0然后2_0 .... 9_0 ... 10_0..11_0 ... 19_0 ... 20_0 ....等?

以下是我的意见:

reg_0_0/clk 
reg_10_0/clk 
reg_11_0/clk 
reg_12_0/clk 
reg_13_0/clk 
reg_14_0/clk 
reg_15_0/clk 
reg_16_0/clk 
reg_17_0/clk 
reg_18_0/clk 
reg_19_0/clk 
reg_1_0/clk 
reg_20_0/clk 
reg_21_0/clk 
reg_22_0/clk 
reg_23_0/clk 
reg_24_0/clk 
reg_25_0/clk 
reg_26_0/clk 
reg_27_0/clk 
reg_28_0/clk 
reg_29_0/clk 
reg_2_0/clk 
reg_30_0/clk 
reg_31_0/clk 
reg_3_0/clk 
reg_4_0/clk 
reg_5_0/clk 
reg_6_0/clk 
reg_7_0/clk 
reg_8_0/clk 
reg_9_0/clk 
s_reg_0_0/clk 
s_reg_10_0/clk 
s_reg_11_0/clk 
s_reg_12_0/clk 
s_reg_13_0/clk 
s_reg_14_0/clk 
s_reg_15_0/clk 
s_reg_16_0/clk 
s_reg_17_0/clk 
s_reg_18_0/clk 
s_reg_19_0/clk 
s_reg_1_0/clk 
s_reg_20_0/clk 
s_reg_21_0/clk 
s_reg_22_0/clk 
s_reg_23_0/clk 
s_reg_24_0/clk 
s_reg_25_0/clk 
s_reg_26_0/clk 
s_reg_27_0/clk 
s_reg_28_0/clk 
s_reg_29_0/clk 
s_reg_2_0/clk 
s_reg_30_0/clk 
s_reg_31_0/clk 
s_reg_3_0/clk 
s_reg_4_0/clk 
s_reg_5_0/clk 
s_reg_6_0/clk 
s_reg_7_0/clk 
s_reg_8_0/clk 
s_reg_9_0/clk 

4 个答案:

答案 0 :(得分:1)

我认为坏消息是,你做不到。你没有数字,你有人眼可以识别为数字的东西,但排序不够聪明,无法解析数字并对其进行排序。你必须编写一些自定义软件才能完成它。

答案 1 :(得分:1)

大多数现代系统上的sort命令能够选择字段并以数字方式对特定字段进行排序。例如:

sort -t _ -k 2 input.txt

这适用于看起来像reg_1_0.txt的行。当然,它不适用于排序字段前包含额外下划线的行,例如s_reg_1_0.txt,您需要-k 3

但有一些技巧。

sed 's/[^0-9]*\([0-9]*\)\(.*\)/\1 &/' input.txt | sort -n | cut -d ' ' -f 2-

这将重写输入文件,以便排序字段位于行的开头。然后按数字排序,然后删除每行的第一个“字段”以恢复原始内容的外观。全部使用无处不在的shell工具。

答案 2 :(得分:1)

您可以通过awk传递文件,根据模式(reg_ vs s_reg)提取数字,将其添加为额外字段,然后对其进行排序。最后使用cut来移除额外的字段。

awk -F_ '/^reg/ { print $0":"$2 } /^s_reg/ { print $0":"$3 }' file | sort -t: -k2,2n | cut -f1 -d:

假设只有两种模式,上述命令可以进一步简化为:

awk -F_ '/^reg/ { print $0":"$2; next } { print $0":"$3 }' file | sort -t: -k2,2n | cut -f1 -d:

生成此输出:

reg_0_0/clk
s_reg_0_0/clk
reg_1_0/clk
s_reg_1_0/clk
reg_2_0/clk
s_reg_2_0/clk
reg_3_0/clk
s_reg_3_0/clk
reg_4_0/clk
s_reg_4_0/clk
reg_5_0/clk
s_reg_5_0/clk
reg_6_0/clk
s_reg_6_0/clk
reg_7_0/clk
s_reg_7_0/clk
reg_8_0/clk
s_reg_8_0/clk
reg_9_0/clk
s_reg_9_0/clk
reg_10_0/clk
s_reg_10_0/clk
reg_11_0/clk
s_reg_11_0/clk
reg_12_0/clk
s_reg_12_0/clk
reg_13_0/clk
s_reg_13_0/clk
reg_14_0/clk
s_reg_14_0/clk
reg_15_0/clk
s_reg_15_0/clk
reg_16_0/clk
s_reg_16_0/clk
reg_17_0/clk
s_reg_17_0/clk
reg_18_0/clk
s_reg_18_0/clk
reg_19_0/clk
s_reg_19_0/clk
reg_20_0/clk
s_reg_20_0/clk
reg_21_0/clk
s_reg_21_0/clk
reg_22_0/clk
s_reg_22_0/clk
reg_23_0/clk
s_reg_23_0/clk
reg_24_0/clk
s_reg_24_0/clk
reg_25_0/clk
s_reg_25_0/clk
reg_26_0/clk
s_reg_26_0/clk
reg_27_0/clk
s_reg_27_0/clk
reg_28_0/clk
s_reg_28_0/clk
reg_29_0/clk
s_reg_29_0/clk
reg_30_0/clk
s_reg_30_0/clk
reg_31_0/clk
s_reg_31_0/clk

答案 3 :(得分:1)

这是一种方法:

sed 's/g_/,/g' data.txt | sort -k2 -t, -n | sed 's/,/g_/g'

(假设data.txt是要排序的行的文件)

由于要排序的某些元素有两个下划线而不是一个,但sort只接受一个字符字段分隔符,您可以使用sed将“g_”替换为“,”,这样在此之前只有一个唯一的分隔符每个的数字(所以数字总是第二个字段)。然后在排序之后,再次通过sed过滤它并用“g _”替换“,”。

输出:

reg_0_0/clk 
s_reg_0_0/clk 
reg_1_0/clk 
reg_2_0/clk 
reg_3_0/clk 
reg_4_0/clk 
reg_5_0/clk 
reg_6_0/clk 
reg_7_0/clk 
reg_8_0/clk 
reg_9_0/clk 
reg_10_0/clk 
s_reg_10_0/clk 
reg_11_0/clk 
s_reg_11_0/clk 
reg_12_0/clk 
s_reg_12_0/clk 
reg_13_0/clk 
s_reg_13_0/clk 
reg_14_0/clk 
s_reg_14_0/clk
reg_15_0/clk 
reg_16_0/clk 
reg_17_0/clk 
reg_18_0/clk 
reg_19_0/clk 
reg_20_0/clk 
reg_21_0/clk 
reg_22_0/clk 
reg_23_0/clk 
reg_24_0/clk 
reg_25_0/clk 
reg_26_0/clk 
reg_27_0/clk 
reg_28_0/clk 
reg_29_0/clk 
reg_30_0/clk 
reg_31_0/clk 

如果您只想要唯一元素,那么只需添加-u标志即可进行排序。