ファイルをソートしたいです。
入力する:
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
入力ファイルが逆順にソートされます。infile
2番目のフィールド(カンマは区切り文字)はk
eyフィールドとして機能します。これアッコードは、単に同じ最初の列にレコードを並べ替えることによって、各グループを区別します。無効特徴
\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] = $0
print val[i][j]
- その要素の値に基づいて配列を繰り返し
PROCINFO["sorted_in"]
、そのインデックス値に基づいて(常に昇順にソート)(単一)配列を繰り返します。列2と同じ最小値を共有する列1の値のソート順を変更したい場合(例:サンプルデータに追加して出力する前にソートしたい場合)、自分で定義する必要があります。ソート機能) 。grp
val[i]
I4, -9
I4
I2
以下に基づくポータブル代替シュワルツ変換、おそらく:
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回処理します)。