基于第三列进行数字排序,然后根据第一列的最后一个字符(非固定长度)进行字母数字排序,在bash中不使用固定分隔符

基于第三列进行数字排序,然后根据第一列的最后一个字符(非固定长度)进行字母数字排序,在bash中不使用固定分隔符,bash,sorting,awk,sed,Bash,Sorting,Awk,Sed,我正在尝试根据第一个第三列的数字以及第一列的最后一个字符对第三列的文本文件进行排序。以下是一个例子: AB2 S 12 ABRT6 E 23 A3 S 2 ABC5 E 34 ABRT4 S 23 预期产出应为: A3 S 2 AB2 S 12 ABRT4 S 23 ABRT6 E 23 ABC5 E 34 我研究了相关的问题,但所有问题都假设第一列中数字部分的长度有一个固定的索引,或者第一列中的字符和数字之间有一个已知的分隔符。现在我正在尝试下面的命令,但是当第三列相同时,它无法基于第一列

我正在尝试根据第一个第三列的数字以及第一列的最后一个字符对第三列的文本文件进行排序。以下是一个例子:

AB2 S 12
ABRT6 E 23
A3 S 2
ABC5 E 34
ABRT4 S 23
预期产出应为:

A3 S 2
AB2 S 12
ABRT4 S 23
ABRT6 E 23
ABC5 E 34
我研究了相关的问题,但所有问题都假设第一列中数字部分的长度有一个固定的索引,或者第一列中的字符和数字之间有一个已知的分隔符。现在我正在尝试下面的命令,但是当第三列相同时,它无法基于第一列进行排序。有什么建议吗

sort -k3,3n -k1,1

您可以使用
sed
在最后一个字符之前插入空格,然后进行排序,然后再次使用
sed
删除插入的空格:

sed 's/\(.\) / \1 /' input \
| sort -k4,4n -k2,2 \
| sed 's/ //'

下面是一个gnu awk命令,它使用
PROCINFO[“sorted_in”]
在单个命令中执行此操作:

  • PROCINFO[“sorted_in”]=“@ind_num_asc”
    将awk数组的默认顺序设置为数字索引
  • a[$3,substr($1,length($1),1)]=$0
    使用复合键作为第三列和第一列的最后一个字符填充数组。值为
    $0
  • END
    块中,我们只需循环遍历数组并打印值部分(整行)

    • @choroba的解决方案很聪明,下面是另一个使用
      cut
      s的解决方案。使用
      rev
      获取最后一个字符

      $ paste file <(cut -d' ' -f1 file | rev | cut -c1) \
                 | sort -k3n                             \
                 | cut -f1
      
      A3 S 2
      AB2 S 12
      ABRT4 S 23
      ABRT6 E 23
      ABC5 E 34
      

      $paste file使用
      awk
      添加另一列,该列包含第一列的最后一个字符。通过管道将其输送至
      排序
      ,然后通过管道输送至
      剪切
      ,以删除多余的列。除非是我,否则您的示例数据不具有说服力;您的
      sort-k3,3n-k1,1
      生成所需的输出。如果您添加了一个条目
      ABBT9 X 23
      ,则
      ABBT9
      条目将在
      ABRT4
      之前排序,但您确实希望它在后面出现,因为后面的数字9位于后面的数字4之后。对吗?如果是这样,我认为“只是排序”不会有帮助,因为它没有一个类似于“负列偏移量”的概念,可以使用:
      -k1.-1,1.-1
      。可以添加这样的符号,但您必须这样做。
      $ paste file <(cut -d' ' -f1 file | rev | cut -c1) \
                 | sort -k3n                             \
                 | cut -f1
      
      A3 S 2
      AB2 S 12
      ABRT4 S 23
      ABRT6 E 23
      ABC5 E 34