首页 > 解决方案 > 如何按字母顺序对第二列进行排序,然后在 shell 脚本中按数字排序?

问题描述

我有一个如下的文本文件:

信息.txt

files-550519470 19h
files-1662192679 1d
files-247106034 1d
files-1986982365 2d
files-464153317 12m
files-739420408 3d
files-77614277 3m
files-374059185 4d
files-909323637 4d
files-101830442 5d
files-1270496134 5d
files-1797797160 6d
files-812888216 7d
files-118869238 7h

我想根据第二列字母进行排序,然后在同一第二列中的数字降序排列,输出应如下所示:

 files-812888216 7d
 files-1797797160 6d
 files-101830442 5d
 files-101830442 5d
 files-1270496134 5d
 files-374059185 4d
 files-909323637 4d
 files-374059185 4d
 files-909323637 4d
 files-739420408 3d
 files-1986982365 2d
 files-1662192679 1d
 files-247106034 1d
 files-550519470 19h
 files-118869238 7h
 files-464153317 12m
 files-77614277 3m

我可以通过以下命令根据数字反转,但无法弄清楚字母表。有人可以建议吗?

 sort -r -nk2 info.txt

标签: shellunix

解决方案


使用Decorate、Sort、Undecorate模式:

$ sort -t $'-' -k 2 file | 
sed -E 's/(.*) ([[:digit:]][[:digit:]]*)([dmh]$)/\2 \3 \1 \2\3/' | 
awk 'BEGIN{arr["m"]=1; arr["h"]=60; arr["d"]=60*24}
     {$2=$1*arr[$2]; $1=""; print}' | 
sort -s -k1nr |
cut -d' ' -f3-
files-812888216 7d
files-1797797160 6d
files-101830442 5d
files-101830442 5d
files-1270496134 5d
files-374059185 4d
files-374059185 4d
files-909323637 4d
files-909323637 4d
files-739420408 3d
files-1986982365 2d
files-1662192679 1d
files-247106034 1d
files-550519470 19h
files-118869238 7h
files-464153317 12m
files-77614277 3m

这应该比 Bash 循环快得多。如果您必须gawk更换sortsed


如果您有 GNU 或 BSD 排序,您可以利用字母顺序d<h<m而不进行转换:

$ sed -E 's/([^-]*)-(.*) ([[:digit:]][[:digit:]]*)([dmh]$)/\2 \4 \3 \1-\2 \3\4/' file |
sort -s -t $' ' -k2,2 -k3,3nr -k1,1 |
cut -d $' ' -f4-
# same output

推荐阅读