【问题标题】:how to sort the line of a file by to the second word from the end如何将文件的行从末尾的第二个单词排序
【发布时间】:2016-10-08 08:57:38
【问题描述】:

我想根据space 之前的最后一个数字对行进行排序。这是一个简化的例子:

c3_abl_eerf_14 sasw
a.bla_haha_2 dnkww
s.hey_3 ddd

这就是我想要的结果:

a.bla_haha_2 dnkww
s.hey_3 ddd
c3_abl_eerf_14 sasw

我不知道该怎么做,也许是通过命令sort?而且,有时我使用sort 命令,它可能会错误地将14 小于2,我不希望这种情况发生。

【问题讨论】:

  • 您不能使用sort 执行此操作,因为它只接受单个字符作为字段分隔符。要按数字排序,请使用sort -n

标签: shell sorting awk sed cut


【解决方案1】:

此命令链适用于您的示例:

sed -r 's/.*_([0-9]+) .*/\1 &/' file|sort -n|sed 's/[^ ]* //'

想法是

  • 先提取数字,添加到行首
  • 按此编号对所有行进行排序
  • 删除号码

更新

按行中的最后一个数字排序,无论数字在哪里:

awk -F'[^0-9]+' '{$0=(length($NF)?$NF:$(NF-1)) OFS $0}7' file|sort -n|sed 's/[^ ]* //'

【讨论】:

  • 谢谢!但我不是很明白它是如何工作的。 .*_([0-9]+) .* 是否匹配 _[a number]?而\1 &/ 表示复制到开头?我对 & 以及最后一个 sed 命令如何工作感到困惑?
  • 而且,这是一个简化的例子。可能有很多_[numbers],但我只想匹配最后一个。更一般地说,可能没有_,数字只是直接与字符相邻。我该怎么办?只是根据一行的最后一个数字。
  • @springcc 你可以举一个简单的例子,但它应该代表你的所有要求。所以你的意思是,以每行的最后一个数字作为键,不管有空格/下划线还是什么?
  • 当然,在这种情况下,我想将最后一个数字作为键。而且我也很好奇怎么取倒数第二个数字作为key。
  • @springcc 检查答案中的 update。不管它在哪一列,它都取最后一个数字进行排序。
【解决方案2】:

如果你想用 GNU awk 来做,试试这个:

BEGIN { FS = "[ _]+" }
{ data[$(NF-1)] = data[$(NF-1)] "\n" $0}
END {
    n = asorti(data, sorted, "@val_num_asc");
    for (i = 1; i <= n; i++) {
        print substr(data[sorted[i]], 2);
    }
}

它的工作原理如下:BEGIN 规则设置字段分隔符(您也可以在命令行上执行此操作)。第二条规则适用于输入的所有行,并将它们放入由第二个但最后一个字段中的数字索引的关联数组中。 END 规则将此数组的索引排序到第二个数组中,然后以下循环打印值,现在已排序。

【讨论】:

  • 如果多行具有相同的编号,例如将最后一行中的3 更改为2 您的命令将打印什么? awk 不会自动解决哈希表键冲突。
  • 它将以正确的顺序打印这两行。排序是稳定的。
  • 好吧,我的错,我没有测试。另一件事,如果你使用 asorti,你应该设置 "sorted_in" 以使其按数字排序。
  • @MichaelVehrs 谢谢,不过,这超出了我的理解,你能简单解释一下吗?我不明白BEGINENDasortisorted[ _]+$0 等函数以及{ data[$(NF-1)] = data[$(NF-1)] "\n" $0} 的工作原理。
猜你喜欢
  • 1970-01-01
  • 2018-08-22
  • 1970-01-01
  • 1970-01-01
  • 2023-03-09
  • 2015-07-22
  • 1970-01-01
  • 1970-01-01
  • 2022-01-09
相关资源
最近更新 更多