ファイルの終わりに達するまでデータブロックを再フォーマットする方法は?

ファイルの終わりに達するまでデータブロックを再フォーマットする方法は?

次のファイルがあります。

# Time-averaged data for fix avetimeall
# TimeStep Number-of-rows
# Row c_gyrationchunkall
1000 3
1 2.09024e-14
2 4.88628
3 5.69321
2000 3
1 2.10518e-14
2 8.33702
3 8.83162
3000 3
1 1.96656e-14
2 12.1396
3 11.5835
...

私のファイルでは、最初の3行は常にヘッダです。ヘッダーの後には、私のファイルに同じサイズのチャンクがリストされており、それぞれはタグサブヘッダーで始まります。各チャンクのデータがそのチャンクラベルの関連部分で始まる行に転送されるようにファイル内のデータを再構成し、そのチャンクの関連データ値をすべてスペースで区切ってリストしたいと思います。たとえば、上記の例を次のように変換したいとします。

# Time-averaged data for fix avetimeall
# TimeStep c_gyrationchunkall
1000 2.09024e-14 4.88628 5.69321
2000 2.10518e-14 8.33702 8.83162
3000 1.96656e-14 12.1396 11.5835
...

Bashでこれを行うにはどうすればよいですか? Bashの経験は少しありますが、この問題をすばやく処理するのに十分ではありません。

ベストアンサー1

3ブロックの行数が異なる可能性があるかどうかに関係なく、awkを使用してください。

$ awk '
    NR == 2 { $3=""; saved=$0; next }
    NR == 3 { $0=saved $3 }
    NR  < 4 { print; next }
    !numLines {
        numLines = $2
        printf "%s%s", $1, OFS
        next
    }
    { printf "%s%s", $2, (--numLines ? OFS : ORS) }
' file
# Time-averaged data for fix avetimeall
# TimeStep c_gyrationchunkall
1000 2.09024e-14 4.88628 5.69321
2000 2.10518e-14 8.33702 8.83162
3000 1.96656e-14 12.1396 11.5835

以下の議論を続けてください。ザビエルGの答え読みやすさスタイルのデフォルト設定に関して、以下はシェルスクリプトと同じスタイルで書かれたawkスクリプトです(シェルスクリプトに含まれているため、外部でも同じように機能します)。しかし、はるかに速く実行されます*シェルスクリプトよりも強力で移植可能です。 :

$ cat ./script_filename
#!/usr/bin/env bash

awk '
    BEGIN {
        # Reformat comments:
        getline first_line
        print first_line
        getline; split($0,line2)
        getline; split($0,line3)
        printf "# %s %s\n", line2[2], line3[3]

        # Reformat data:
        while ( getline > 0 ) {
            timestep=$1; number_of_rows=$2
            printf "%s", timestep
            for ( i=1; i<=number_of_rows; i++ ) {
                getline; row_value=$NF
                printf " %s", row_value
            }
            print ""
        }
    }
'

$ ./script_filename < input
# Time-averaged data for fix avetimeall
# TimeStep c_gyrationchunkall
1000 2.09024e-14 4.88628 5.69321
2000 2.10518e-14 8.33702 8.83162
3000 1.96656e-14 12.1396 11.5835

*以下は、90,000個のOPレコードを含むファイルでbashスクリプトと上記のawkスクリプトを3回目に実行したタイミングの結果です。

$ time ./script_bash < file > /dev/null

real    0m9.425s
user    0m5.062s
sys     0m4.139s

$ time ./script_awk < file > /dev/null

real    0m0.265s
user    0m0.171s
sys     0m0.000s

おすすめ記事