【问题标题】:Sort based on third column numerically and then last character of first column (non-fixed length) alphanumerically without a fixed delimiter in bash基于第三列数字排序,然后是第一列的最后一个字符(非固定长度)按字母数字排序,bash 中没有固定分隔符
【发布时间】:2016-03-25 16:06:41
【问题描述】:

我正在尝试根据第一个第三列的数字,然后是第一列的最后一个字符,对具有第三列的文本文件进行排序。这是一个例子:

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

【问题讨论】:

  • 使用awk 添加另一列,其中包含第一列的最后一个字符。将其通过管道传输到 sort,然后通过管道传输到 cut 以删除多余的列。
  • 除非只有我,否则你的样本数据没有说服力;您的 sort -k3,3n -k1,1 生成所需的输出。如果您添加了一个条目ABBT9 X 23,那么ABBT9 条目将排在ABRT4 之前,但是您真的希望它出现在之后,因为尾随数字9 出现在尾随数字4 之后。正确吗?如果是这样,我认为“仅排序”将无济于事,因为它没有类似于可以使用的“负列偏移”的概念:-k1.-1,1.-1。可以添加这样的符号——但你必须这样做。

标签: bash sorting awk sed


【解决方案1】:

可以使用sed在最后一个字符前插入一个空格,然后排序,再次使用sed去掉插入的空格:

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

【讨论】:

    【解决方案2】:

    这是一个 gnu-awk 命令,它使用 PROCINFO["sorted_in"] 在单个命令中执行:

    awk 'BEGIN{PROCINFO["sorted_in"] = "@ind_num_asc"} {a[$3,substr($1, length($1), 1)] = $0}
         END{for(i in a) print a[i]}' file
    A3 S 2
    AB2 S 12
    ABRT4 S 23
    ABRT6 E 23
    ABC5 E 34
    
    • PROCINFO["sorted_in"] = "@ind_num_asc" 将 awk 数组的默认顺序设置为数字索引。
    • a[$3,substr($1, length($1), 1)]=$0 使用复合键作为第三列和第一列的最后一个字符填充数组。值为$0
    • END 块中,我们只是循环遍历数组并打印值部分(整行)。

    【讨论】:

      【解决方案3】:

      @choroba 的解决方案很聪明,这里是另一个使用cuts 的解决方案。使用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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-11
        • 1970-01-01
        • 2021-12-20
        • 1970-01-01
        • 2018-11-02
        相关资源
        最近更新 更多