我正在尝试对多列进行排序。结果并不如预期。
这是我的数据(people.txt):
Simon Strange 62
Pete Brown 37
Mark Brown 46
Stefan Heinz 52
Tony Bedford 50
John Strange 51
Fred Bloggs 22
James Bedford 21
Emily Bedford 18
Ana Villamor 44
Alice Villamor 50
Francis Chepstow 56
Run Code Online (Sandbox Code Playgroud)
以下工作正常:
bash-3.2$ sort -k2 -k3 <people.txt
Emily Bedford 18
James Bedford 21
Tony Bedford 50
Fred Bloggs 22
Pete Brown 37
Mark Brown 46
Francis Chepstow 56
Stefan Heinz 52
John Strange 51
Simon Strange 62
Ana Villamor 44
Alice Villamor 50
Run Code Online (Sandbox Code Playgroud)
但是,以下内容无法按预期工作:
bash-3.2$ sort -k2 -k1 <people.txt
Emily Bedford 18
James Bedford 21
Tony Bedford 50
Fred Bloggs 22
Pete Brown 37
Mark Brown 46
Francis Chepstow 56
Stefan Heinz 52
John Strange 51
Simon Strange 62
Ana Villamor 44
Alice Villamor 50
Run Code Online (Sandbox Code Playgroud)
我试图按姓氏排序,然后按名字排序,但您会看到 Villamors 的顺序不正确。我希望按姓氏排序,然后当姓氏匹配时,按名字排序。
似乎我不明白这应该如何工作。我当然可以用另一种方式(使用 awk)来做到这一点,但我想了解排序。
我在 Mac OS X 上使用标准的 Bash shell。
Gil*_*il' 213
像关键规范一样-k2意味着考虑从 2 到行尾的所有字段。所以Villamor 44在Villamor 50. 由于这两个不相等,所以第一次比较sort -k2 -k1就足以区分这两行,第二个排序键-k1没有被调用。如果两个Villamors的年龄相同,-k1就会导致他们按名字排序。
要按单列排序,请-k2,2用作键规范。这意味着使用从#2 到#2 的字段,即仅使用第二个字段。
sort -k2 -k3 <people.txt是多余的:它相当于sort -k2 <people.txt. 要按姓氏、名字、年龄排序,请运行以下命令:
sort -k2,2 -k1,1 <people.txt
Run Code Online (Sandbox Code Playgroud)
或者等效地,sort -k2,2 -k1 <people.txt因为只有这三个字段并且分隔符是相同的。事实上,您将从 中获得相同的效果sort -k2,2 <people.txt,因为sort当行子集中的所有键都相同时,将整行用作最后的手段。
另请注意,默认字段分隔符是非空白和空白之间的过渡,因此键将包括前导空白(在您的示例中,对于第一行,第一个键是"Emily",但第二个键是" Bedford"。添加-b去除这些空白的选项:
sort -b -k2,2 -k1,1
Run Code Online (Sandbox Code Playgroud)
也可以通过在b密钥启动规范的末尾添加标志来基于每个密钥来完成:
sort -k2b,2 -k1,1 <people.txt
Run Code Online (Sandbox Code Playgroud)
但是要记住一点:一旦您将一个这样的标志添加到密钥规范中,全局标志(如-n, -r...)就不再适用于它们,因此最好避免混合按键标志和全局标志。
man*_*ork 20
使用 GNU,sort您可以这样做,但不确定 MacOS:
sort -k2,2 -k1 <people.txt
Run Code Online (Sandbox Code Playgroud)
根据评论更新。引用自man sort:
-k, --key=KEYDEF
sort via a key; KEYDEF gives location and type
KEYDEF is F[.C][OPTS][,F[.C][OPTS]] for start and stop position, where
F is a field number and C a character position in the field; both are
origin 1, and the stop position defaults to the line's end.
Run Code Online (Sandbox Code Playgroud)