行ブロックの並べ替え


12

4n行を含むファイルがあります。これは、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 

回答:


17

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' '

7

これが1回だけで、Python、perl、またはawkを学習したくない場合は、基本コマンドsplitsortコマンドを使用できます。

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

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 -> anyの出力に改行を追加します print
  • -e -> Perlコードとして次の文字列を実行します
  • 各行は配列に追加され@aます。
  • $.現在の行番号を保持し、その番号が4を法とするゼロと一致しない場合を除き、作業を続けます。それは場合であるゼロモジュロ4と合同、我々は、その番号4(ブロックの最後)の倍数である行に達した場合には、我々ソートエントリ@a数値の昇順にソートし、アレイ内のエントリを印刷します改行で標準出力に結合されます。

2

Bourneのようなシェルを使用して、

while read a ; do                                           # Try reading a line.
    read b ; read c ; read d                                # OK, read 3 more.
    printf '%s\n%s\n%s\n%s\n' "$a" "$b" "$c" "$d" | sort -n # Sort them.
done < data

2

いくつかの「純粋な」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}'

注:@Gillesのdelete TIL self-answer(+2)この使用は(まだ)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++}

1

Rでクリーンなソリューションを取得できます。上記の表が「table.txt」というファイルにある場合は、次の手順を実行します。望ましい結果は、ファイル「tableout.txt」にあります。

> x = read.table("table.txt", col.names=c("a", "b"))
> x
     a        b
1 6115  8.88443
2 6116  6.61875
3 6118 16.59490
4 6117 19.41290
5 6116  6.61900
6 6117 16.59790
7 6118 19.41110
8 6115  8.88433
> x["index"] = c(rep(1, 4), rep(2, 4))
> x
     a        b index
1 6115  8.88443     1
2 6116  6.61875     1
3 6118 16.59490     1
4 6117 19.41290     1
5 6116  6.61900     2
6 6117 16.59790     2
7 6118 19.41110     2
8 6115  8.88433     2     
> xord = x[with(x, order(index, a)), ]
> xord
     a        b index
1 6115  8.88443     1
2 6116  6.61875     1
4 6117 19.41290     1
3 6118 16.59490     1
8 6115  8.88433     2
5 6116  6.61900     2
6 6117 16.59790     2
7 6118 19.41110     2
> write.table(xord[,1:2], "tableout.txt", row.names=FALSE, col.names=FALSE)

Rの列でデータフレームをソートする方法も参照してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.