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


106

複数の列でソートしようとしています。結果は期待どおりではありません。

これが私のデータ(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シェルを使用しています。

回答:


159

のようなキー仕様-k2は、2から行末までのすべてのフィールドを考慮することを意味します。だからVillamor 44前に終わるVillamor 50。これらの2つは等しくないため、最初の比較でsort -k2 -k1これらの2行を区別するのに十分であり、2番目のソートキー-k1は呼び出されません。2つのVillamorsの年齢が同じだった場合、-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 -k2,2 <people.txtため、から同じ効果が得られますsort

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

sort -b -k2,2 -k1,1

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

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

しかし、何かが心に留めて:あなたは鍵仕様にそのようなフラグを追加するとすぐとして、グローバルフラグ(のような-n-rそれがあたりのキーフラグおよびグローバルフラグの混合を避けるために、より良いですので...)もはやそれらに適用されません。


6
あなたはそれを打ちました。-k1を指定すると、フィールド1がデフォルトのフィールド区切り記号(スペース)で終わるフィールド1が使用されることを意味すると想定しました(危険なこと)。しかし、明確に指摘しているように、kオプションは、キーの開始点と終了点を指定することを期待しています。これは、単一のフィールドである場合とそうでない場合があります。あなたのソリューションは完璧に機能します。さらに重要なことは、なぜそれが機能するのか明確です。どうもありがとう。
ハリー

これは巨大です。KEYDEFに関する他の多くの情報源は、各ソートステップで考慮される列を制限する形式でのCOMMAの重要性を強調せずに-k1 -k2について語っています。この答えを見つけるまで、私は何時間もこれに固執しました。そして、manページはここで混乱しています。「開始と停止」の場所がカンマ表記で指定されていることは説明されていません。ありがとうございました!
ジェイソンローラー

16

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.

4
この奇妙な表記を説明していただけますか?
scai

1
これは私に正しい線に沿って考えさせました-それに感謝します。ただし、2番目の-kのストップポイントを指定する必要はありません。それは-k2,2 -k1,1です
ハリー

@TonyBedford、正しい。ただし、停止位置を指定しなくても、現在の入力の結果は変わりませんが、フィールド2と1が同じ複数の行がある場合、一貫性が強制されます-k
マナトワーク

1
@manatworkそれは必要ではないはずです。指定されたすべてのフィールドが等しい場合、sort行全体を比較します。または、GNU sortを使用すると-s、安定したソートに使用できます。
8
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.