在bash中按多个列排序

17
我有一个包含“姓名”和“年龄”两列的文件,长成这个样子:
Alex,  15
Mary,  12
Alex,  28
Zoe,   16
Alex,  17

我将按照第一列的字母顺序排序,使用sort -t ',' -k1,1 filename.txt命令,但如果有相同的名称,我希望第二列按照它们在原始文件中的相反顺序进行排序,就像这样:

Alex,  17
Alex,  28
Alex,  15
Mary,  12
Zoe,   17

我该怎么做这件事?

5个回答

20
sort -t ',' -k1,1 -k2,2r filename.txt

或者
sort -t ',' -k1,1 -k2r,2 filename.txt

输出结果如下:
Alex,  28
Alex,  17
Alex,  15
Mary,  12
Zoe,   16

解释: -t 用于指定字段分隔符,-k 可以用于指定字段的起始和结束位置,我们可以为该字段添加一个单字母 OPTS 进行排序,例如 r 表示反转比较结果。


3
这不是 OP 所要求的。 - MrCricket

6
从后往前读取文件,按第一列排序,并使用“-s”选项以保留相同值的顺序。
tac filename.txt | sort -k1,1 -s
...
Alex,  17
Alex,  28
Alex,  15
Mary,  12
Zoe,   16

1
你可以接受我的答案,这样就更能表示感谢了;P - Tomáš Šíma

3
抱歉,我之前误解了您的问题。我找不到一个神奇的命令,但是一个小脚本可能可以解决问题:
#! /bin/bash
declare names_sorted=$(cut -d, -f1 filename.txt | sort -k1,1 | uniq)
for name in $names_sorted ; do
    grep "$name," filename.txt | tac
done

快速解释:

  1. 首先,我们组装已排序的名称列表:$names_sorted
  2. 接下来(假设名称不包含空格),我们使用命令tac从原始列表中grep每个名称并倒转该顺序。

希望这次是您想要的内容;-)


2
这应该能给你想要的结果:
sort -k1,1 -k2,2 filename.txt

3
不,-k2,2 再次按字母顺序排序,我想以文件中第一次出现的相反方式对年龄列进行排序。 - Alex

1
tac filename.txt | sort -t"," -k1,1 -s

说明:

  • tac 将按照反向顺序排序输出。
  • -t"," 定义字段分隔符。
  • -k1,1 仅限定在第一个排序列上。
  • -s 保留已排序行内的顺序。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接