1

我有一个文件,例如

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”之前——不是相反。没有“boom”,没有 2 个“aargh”!:))。

我想要的是:

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

这是为什么?那是一个错误吗?更重要的是,如何让 sort 表现得像我想要的那样?

4

2 回答 2

3

您需要使用此选项:

-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 中就包含了最后的整行比较 - 请参阅1975 年的手册页,其中说

比较相等的行按所有有效字节排序。

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

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

于 2015-05-06T15:51:08.310 回答
1

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

于 2015-05-06T16:07:45.570 回答