2番目のフィールドに基づいて並べ替え、同じ最初の列を使用して行を並べ替えますが、グループごとに2番目のフィールドの順序は維持されます。

2番目のフィールドに基づいて並べ替え、同じ最初の列を使用して行を並べ替えますが、グループごとに2番目のフィールドの順序は維持されます。

ファイルをソートしたいです。

入力する:

I1, -2   
I2, -6  
I2, -9  
I1, -8  
I1, -1  
I3, -7  
I2, -4  
I3, -4  

出力:

I2, -9  
I2, -6  
I2, -4  
I1, -8  
I1, -2  
I1, -1  
I3, -7  
I3, -4

以下の出力をどのように取得できますか?

答え1

汚れた解決策は次のとおりです。

<infile sort -t, -rk2,2 \
|awk -F, '{ seen[$1]= (seen[$1]==""? "\0":seen[$1] ORS) $0 }
 END{ for (x in seen) print seen[x] }' \
|sort -z -t, -rk2,2 \
|tr -d '\0'

分解:

  • <infile sort -t, -rk2,2
    これにより、r入力ファイルが逆順にソートされます。infile2番目のフィールド(カンマは区切り文字)はkeyフィールドとして機能します。

  • これアッコードは、単に同じ最初の列にレコードを並べ替えることによって、各グループを区別します。無効特徴\0

  • sort -z -t, -rk2,2
    -zこの逆方向ソートは、2番目のフィールドとカンマで区切られたフィールド(ヌル文字で区切られ、Tell-sortコマンドを使用)でこれらのブロックをソートします。この手順を実行する前に、次の出力を確認して表示さcat -Aれる内容を追加してください。

    ^@I1, -8$
    I1, -2$
    I1, -1$
    ^@I2, -9$
    I2, -6$
    I2, -4$
    ^@I3, -7$
    I3, -4$
    

    ^@文字はヌル文字を表します。sort -z上記の入力は次のとおりです(人の読みやすさと理解を助けるためにこれを行いました)。

    ^@I1, -8$      I1, -2$      I1, -1$
    ^@I2, -9$      I2, -6$      I2, -4$
    ^@I3, -7$      I3, -4$
    

    あなたはアイデアを得ました。上記のソートコマンドは、2番目のフィールドを次のように表示します。

     -8$      I1
     -9$      I2
     -7$      I3
    

    ...これを逆順に並べ替えると、結果は次のように変更されます。

    ^@I2, -9$      I2, -6$      I2, -4$
    ^@I1, -8$      I1, -2$      I1, -1$
    ^@I3, -7$      I3, -4$
    

    ...構造体を返すと、実際には次のような結果が表示されます。

    ^@I2, -9$
    I2, -6$
    I2, -4$
    ^@I1, -8$
    I1, -2$
    I1, -1$
    ^@I3, -7$
    I3, -4$
    
  • tr -d '\0'
    結果から追加されたヌル文字が削除され、最終出力は次のようになります。

    I2, -9
    I2, -6
    I2, -4
    I1, -8
    I1, -2
    I1, -1
    I3, -7
    I3, -4
    

答え2

GNUの使用awk:

gawk '
  grp[$1] == "" || $2 < grp[$1] { grp[$1] = $2 }
  { val[$1][$2] }
  END {
    PROCINFO["sorted_in"] = "@val_num_asc"
    for (i in grp) {
      PROCINFO["sorted_in"] = "@ind_num_asc"
      for (j in val[i]) print i,j
    }
  }' ./file

アイデアは次のとおりです。

  • grp配列内の列1の各固有値について、列2の最小値を格納します。
  • 各行を2D配列に保存すると、列1の各固有値に対して列2の値を簡単に取得できます(データの元の間隔を維持して使用することvalもできます)。val[$1][$2] = $0print val[i][j]
  • その要素の値に基づいて配列を繰り返しPROCINFO["sorted_in"]、そのインデックス値に基づいて(常に昇順にソート)(単一)配列を繰り返します。列2と同じ最小値を共有する列1の値のソート順を変更したい場合(例:サンプルデータに追加して出力する前にソートしたい場合)、自分で定義する必要があります。ソート機能) 。grpval[i]
    I4, -9I4I2

以下に基づくポータブル代替シュワルツ変換、おそらく:

sort -k2,2n ./file |
  awk '
    grp[$1] == "" { grp[$1] = $2 }
    { print grp[$1] "," $0 }' |
  sort -t, -k 1,1n -k 2,2 -k 3,3n |
  cut -d, -f2-

ここで、「グループあたり」(つまり、列 1 の値に相対的) 列 2 の最小値は各行の前に追加され、各グループ ( -9, -8, -7) の最小値に基づいて後続のソートが可能になります。列1(グループ化された行を維持するため)、列2の値はソートされた
awkデータを提供し、スクリプトをより簡単にします。各行に対して行が満たされると、各グループの最小値が既に知られているため、必要はありません。いくつかの構造行に保存してENDブロックとして印刷します(またはファイルを2回処理します)。

関連情報