web-dev-qa-db-ja.com

2番目に最初に2つのフィールドでソートしようとしています

複数の列で並べ替えようとしています。結果は期待どおりではありません。

これが私のデータです(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

以下は正しく動作します:

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

ただし、以下は期待どおりに機能しません。

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

姓、名の順に並べ替えようとしましたが、Villamorsの順序が正しくありません。姓で並べ替え、姓が一致したときに名で並べ替えることを望んでいました。

これがどのように機能するかについて私は理解していないようです。もちろんこれを別の方法で(awkを使用して)行うこともできますが、ソートについて理解したいと思います。

Mac OS Xでは標準のBash Shellを使用しています。

111
Harry

-k2のようなキー指定は、2から行の終わりまでのすべてのフィールドを考慮することを意味します。したがって、Villamor 44Villamor 50より前に終了します。これら2つは等しくないため、sort -k2 -k1の最初の比較でこれら2つの行を区別でき、2番目のソートキー-k1は呼び出されません。 2人のビジャモールが同じ年齢だった場合、-k1により、姓で並べ替えられることになります。

単一の列でソートするには、-k2,2をキー指定として使用します。これは、#2から#2までのフィールド、つまり2番目のフィールドのみを使用することを意味します。

sort -k2 -k3 <people.txtは冗長です:sort -k2 <people.txtと同等です。姓、名、年齢の順に並べ替えるには、次のコマンドを実行します。

sort -k2,2 -k1,1 <people.txt

または同等のsort -k2,2 -k1 <people.txtこれらの3つのフィールドのみがあり、セパレーターは同じであるため。実際、sortは行のサブセットのすべてのキーが同一である場合、最後の手段として行全体を使用するため、sort -k2,2 <people.txtから同じ効果が得られます。

また、デフォルトのフィールドセパレーターは非空白と空白の間の遷移であるため、キーには先頭の空白が含まれます(例では、最初の行の場合、最初のキーは"Emily"になりますが、 2番目のキー" Bedford"-bオプションを追加して、これらの空白を削除します。

sort -b -k2,2 -k1,1

また、キーの開始指定の最後にbフラグを追加することで、キーごとに行うこともできます。

sort -k2b,2 -k1,1 <people.txt

ただし、覚えておかなければならないことがあります。そのようなフラグをキーの仕様に追加するとすぐに、グローバルフラグ(-n-r...など)が適用されなくなるため、できるだけ避けてください。キーごとのフラグとグローバルフラグの混在。

GNU sortを使用すると、MacOSについてはわかりませんが、次のように実行します。

sort -k2,2 -k1 <people.txt

更新コメント通り。 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.
16
manatwork