仅按第一个键排序(保留其余顺序)

sort with first key only (preserve order for rest)

我有一个文件,例如

day1 aargh
day2 boom
day3 crack
day2 argh

并且我想根据第一个键排序,而不是任何其他键,也就是说,我想保留顺序键相同的行数。

没想到会这么简单

$ sort -k1,1 myfile
day1 aargh
day2 aargh
day2 boom
day3 crack

但是哎呀。可以看到,sort 无缘无故把原来的第 4 行放在第 2 行之前,丢掉了原来的顺序。 (在第 2 天。"boom" 在 "aargh" 之前——而不是相反。没有 2 "aargh" 没有 "boom"!:))。

我想要的是:

$ sort -k1,1 myfile
day1 aargh
day2 boom
day2 aargh
day3 crack

这是为什么?那是一个错误吗?更重要的是,如何让排序按照我想要的方式进行?

您需要使用此选项:

-s, --stable
       stabilize sort by disabling last-resort comparison

最后的比较是整行的字符串比较,如果所有键都相等则使用。

下次你遇到 sort 的麻烦时(如果你继续使用它,你肯定会遇到更多麻烦;其中有很多不直观的东西)尝试使用 --debug 来查看正在比较的内容。

如果你只使用这条线:

day2 aargh

并尝试 sort --debug -k1,1 你应该得到这个:

day2 aargh
____
__________

输入行在day2下方显示为一行下划线。这意味着 day2 是该行的最高优先级排序键。它将与其他行的最高优先级排序键进行比较,以决定哪一个排在第一位。由于 -k1,1.

,此密钥包含在密钥列表中

下划线在整行下面。这意味着按优先级降序排列的行的下一个排序关键字是整行。如果 -k1,1 键在一对行中完全相同,这就是接下来要比较的内容。由于缺少 -s.

,此密钥包含在密钥列表中

-s -k1,1 --debug 再试一次,你会看到第二行下划线不见了。

我想不出 sort -k1,1 与没有选项的 sort 表现不同的例子,因为整行比较将从与第一个相同的字节开始-场比较。但是您肯定可以看出 sort -k2,2 具有不同的含义:首先尝试第二个字段,然后是整行。所以 -k1,1 本身就是一种无用的退化情况。

至于 为什么 ... sort 的默认行为至少可以追溯到版本 6 UNIX -看到 the man page from 1975

Lines that compare equal are ordered with all bytes significant.

(而且也没有 -s 选项来禁用它!)

sort 奇怪的默认行为只是我们不得不忍受的历史事件,因为旧的和广泛使用的东西不能更改其默认值。感谢 GNU 的 --debug 选项,这是一个相对较晚的添加,于 2010 年推出。

Wumpus 已经给出了正确答案。我试图将其添加为评论,但它太长了,所以请不要给我投低票:)

"A pair of lines is compared as follows: sort compares each pair of fields, in the order specified on the command line, according to the associated ordering options, until a difference is found or no fields are left. If no key fields are specified, sort uses a default key of the entire line. Finally, as a last resort when all keys compare equal, sort compares entire lines as if no ordering options other than --reverse (-r) were specified. The --stable (-s) option disables this last-resort comparison so that lines in which all fields compare equal are left in their original relative order. The --unique (-u) option also disables the last-resort comparison." sort-invocation