行ブロックのソート

行ブロックのソート

4行行を含むファイルがあります。以下は8行の内容を抜粋したものです。

6115 8.88443
6116 6.61875
6118 16.5949
6117 19.4129
6116 6.619 
6117 16.5979 
6118 19.4111
6115 8.88433  

私がやりたいことは、最初の列に基づいて各ブロックが4つの行で構成されるブロックをソートすることです。抜粋の出力は次のようになります。

6115 8.88443
6116 6.61875
6117 19.4129
6118 16.5949
6115 8.88433 
6116 6.619 
6117 16.5979 
6118 19.4111 

答え1

1つのオプションは、次を使用することです。N行ごとに最初のシーケンス番号プレフィックスを追加します(あなたの場合はN = 4)。次に、デフォルトのソート列としてプレフィックスを入力しますsort

N = 4の例:

awk '{print int((NR-1)/4), $0}' file.txt | sort -n -k1,1 -k2,2 | cut -f2- -d' '

答え2

これがワンタイムであり、Python、Perl、またはawkを学びたくない場合は、基本とsplitコマンドsortを学ぶことができます。

まず、次のオプションを使用してファイルを4行のチャンクに分割します-l

split -a 6 -l 4 input_file my_prefix_
for fn in my_prefix_*; do
    sort -n -o $fn $fn
done
cat my_prefix_* > output_file
rm my_prefix_*

sort -n最初の列の値(1234より前の999)に基づいてソートします。-a 626^6*4 行のファイルを処理する必要があります。my_prefix_使用しているディレクトリに固有のものでなければなりません。

答え3

Perlを使用してこれを行うことができます。

perl -nle '
   push @a,$_;
   unless($. % 4){
       print join "\n",sort {$a <=> $b} @a; # Sort @a, and print its contents
       @a = (); # Empty @a to start a new block
   }
' your_file

どのように動作しますか?

  • -n-->各入力行に対してコードを実行します(そして現在の行をに入れます$_)。
  • -l-->すべての出力に改行を追加します。print
  • -e-->次の文字列をPerlコードとして実行する
  • 各行は配列に追加されます@a
  • $.現在の行番号を保存します。行番号が0モジュールとして4に等しくない場合は、作業を続けます。その場合はい0モジュロ4と一致すると、数字が4の倍数(ブロックの終わり)である行に到達します。この場合、@a項目を昇順に並べ替え、改行文字で連結された整列配列の項目を標準に印刷します。出力。

答え4

以下は「純粋な」awkソリューションです。

例データに示すように、インデックスが常に同じインクリメント順序(6115-6119)である場合は、アルゴリズム「ショートカット」を使用できます。

awk '{a[$1]=$0} !(NR%4){for(i=6115;i<6119;print a[i++]);}'

これは実際に

  • aインデックス位置6115-6119に分散された配列にすべての行を追加します。
  • 4行()ごとに配列の!(NR%4)内容を繰り返し、目的の順序で印刷します。

数値インデックスが常に同じ4つのインデックスですが、増加する整数シーケンスがない場合は、次のようにソートする必要があります。

awk '{a[$1]=$0} !(NR%4){asort(a,b); for(i=1;i<5;print b[i++]);}'

注:これはGNU awk用であるため、他のユーザーはそれをサポートしていない可能性がありますasort


4つのブロックがそれぞれ異なる数値IDを持つことができる場合:

awk '{a[$1]=$0} !(NR%4){asort(a); for(i=1;i<5;print a[i++]); delete a}'

注:TILは以下に由来します。@Gilles自己回答(+2)この使い方はdeleteまだPOSIXではありませんが、一般的にサポートされています。


使用する正しい™バージョンdelete

awk '{a[$1]=$0} !(NR%4){asort(a); for(i=1;i<5;delete a[i++]){print a[i]}}'

より多くのメモリとサイズを使用して削除されなかったバージョン:

awk '{a[n][$1]=$0} !(NR%4){asort(a[n]); for(i=1;i<5;print a[n][i++]); n++}

関連情報