使用最后一个字段对文本文件进行排序

时间:2019-07-15 13:08:56

标签: linux shell sorting unix

我有如下所示的文本文件:

cc_1 ( AB GND ) capacitor c=1.72728p
cc_2 ( AB VIN ) capacitor c=26.9013p
cc_3 ( AB H_SNS ) capacitor c=15.2554p
cc_4 ( AB L_SNS ) capacitor c=2.89517p
cc_5 ( AB VREG ) capacitor c=23.7678f
cc_6 ( AB VIN ) capacitor c=1.34133f

我想按最后一列对该文件排序。最后一列是数字和字符的组合(例如1.72728p)。所以我想先按最后一个字符排序,再按数字排序。因此输出应如下所示:

cc_2 ( AB VIN ) capacitor c=26.9013p
cc_3 ( AB H_SNS ) capacitor c=15.2554p
cc_4 ( AB L_SNS ) capacitor c=2.89517p
cc_1 ( AB GND ) capacitor c=1.72728p
cc_5 ( AB VREG ) capacitor c=23.7678f
cc_6 ( AB VIN ) capacitor c=1.34133f

关于如何实现此输出的任何建议?

3 个答案:

答案 0 :(得分:0)

<input_file sed 's/^.* c=\([0-9\.]*\)\(.\)$/\2 \1 &/' |
xargs printf "%s %030.10f %s %s %s %s %s %s %s\n" |
sort -k1.1r -k2.2n |
cut -d' ' -f3-
  • 首先,输入通过sed。我会加上浮点数和后面的字母。输出变为<letter> <float numbe> <rest of the line
  • 然后我遇到了--generic-sortsort的麻烦*。 --generic-sort还是gnu排序扩展。
  • 因此,我决定格式化浮点数,以使至少20个前导零和在逗号后至少10个数字。我将简单的xargsprintf一起使用。如果30.10对您来说不够精确,则可以随时提高精度(例如100.50)。
  • 然后我排序。我使用<letter>列进行反向排序,然后使用数字进行数字排序。
  • 然后我删除前两个字段。

经过测试:

cat <<EOF >file
cc_1 ( AB GND ) capacitor c=1.72728p
cc_2 ( AB VIN ) capacitor c=26.9013p
cc_3 ( AB H_SNS ) capacitor c=15.2554p
cc_4 ( AB L_SNS ) capacitor c=2.89517p
cc_5 ( AB VREG ) capacitor c=23.7678f
cc_6 ( AB VIN ) capacitor c=1.34133f
cc_6 ( AB VIN ) capacitor c=1.44133f
cc_6 ( AB VIN ) capacitor c=1.24133f
cc_6 ( AB VIN ) capacitor c=12.24133f
cc_6 ( AB VIN ) capacitor c=11.24133f
cc_6 ( AB VIN ) capacitor c=13.24133f
cc_6 ( AB VIN ) capacitor c=13.24133001f
cc_6 ( AB VIN ) capacitor c=13.24133003f
cc_6 ( AB VIN ) capacitor c=13.24133002f
EOF

<file sed 's/^.* c=\([0-9\.]*\)\(.\)$/\2 \1 &/' |
xargs printf "%s %030.10f %s %s %s %s %s %s %s\n" |
sort -k1.1r -k2.2n |
cut -d' ' -f3-

将输出:

cc_2 ( AB VIN ) capacitor c=26.9013p
cc_3 ( AB H_SNS ) capacitor c=15.2554p
cc_4 ( AB L_SNS ) capacitor c=2.89517p
cc_1 ( AB GND ) capacitor c=1.72728p
cc_5 ( AB VREG ) capacitor c=23.7678f
cc_6 ( AB VIN ) capacitor c=13.24133003f
cc_6 ( AB VIN ) capacitor c=13.24133002f
cc_6 ( AB VIN ) capacitor c=13.24133001f
cc_6 ( AB VIN ) capacitor c=13.24133f
cc_6 ( AB VIN ) capacitor c=12.24133f
cc_6 ( AB VIN ) capacitor c=11.24133f
cc_6 ( AB VIN ) capacitor c=1.44133f
cc_6 ( AB VIN ) capacitor c=1.34133f
cc_6 ( AB VIN ) capacitor c=1.24133f
  • 旁注:从理论上讲,我认为以下方法应该有效:

<file sed 's/^.* c=\([0-9\.]*\)\(.\)$/\2 \1 &/' |
sort -s -k1.1r -k2.2g

但是它不能也不正确地对1512进行排序(对数字进行排序,而不是浮点数,因此点.使所有内容无效(显示head -n4,请注意2.815.2大):

p 26.9013 cc_2 ( AB VIN ) capacitor c=26.9013p
p 2.89517 cc_4 ( AB L_SNS ) capacitor c=2.89517p
p 15.2554 cc_3 ( AB H_SNS ) capacitor c=15.2554p
p 1.72728 cc_1 ( AB GND ) capacitor c=1.72728p

答案 1 :(得分:0)

如果数据具有所示格式,特别是只有一个等号(=),则这样做很容易:

sort -t= -r -n -k2,2 datafile |\
rev | sort -s -r -k1.1,1.1 | rev
  • 第一个排序在=处分割,然后按数字排序
  • 然后我们将线倒转,以便容易找到最终字符
  • 然后我们对该单个字符进行稳定排序(稳定意味着排序仅在需要时才更改行顺序(这样就不会丢失前一个排序)
  • 最终撤消冲销

答案 2 :(得分:0)

cat input.txt | awk -F"c=" '{print $NF}' |
while read line ; do echo ${line: -1:1}${line:0:-1} ; done |
sort -k1.1,1.1 -r -k1.2,1.3nr |
while read line ; do grep ${line:1}${line:0:1} input.txt; 
done > result.txt 

首先得到用定界符“ c =”;

用awk排序所需的列。

将最后一个字符替换为开头;

按首字符排序,而不是按其他字符排序; (根据需要进行反向排序);

按排序的列从输入文件到结果文件的行提取。