web-dev-qa-db-ja.com

列パターンによるテキストファイルの解析

Awkまたはその他のコマンドを使用して、次のようなファイルがテキストファイルを解析する簡単な方法があるかどうか疑問に思っていました。

Step Temp Enthalpy
0    0    -368
100  1    -369
200  2    -372
300  6    -362
400  9    -365
SHAKE stats (type/ave/delta) on step 500
1 1.09  8.71362e-08
500  13   -358
600  15   -339
.
.
900  25   -306
SHAKE stats (type/ave/delta) on step 1000
1 1.09 7.06858e-08
1000 28  -306
.
.
.

温度値のみなど、必要な数値の特定の列のみの出力を印刷できます。温度値に対してawk '{print $2}'のようなことができることはわかっていますが、私の特定のデータファイルには、これを非実用的にする 'Step Temp Enthalpy'テーブルの前後にさまざまなデータの他の行があります。この 'Step Temp Enthalpy'情報の前後のすべてを出力し、必要なデータファイルのこのセクションの特定の列のみを出力します。データファイルには、「1 1.09 .... etc」以降の削除したい行に加えて、5ステップごとに「SHAKE stats」行もあります。温度列のみを印刷する場合は、出力したい:

0
1
2
6
9
13
15
.
.
25
28
2
Jonathan Tran

あなたが持っている簡単なパターンは、数字を含む/数字で始まる行の列2を取り出すことです。 awkコマンドの通常の構造は/Pattern in current line/ { commands};です。中括弧内のコマンドは、現在の行でパターンが見つかった場合にのみ実行されます。したがって、次のことができます。

$ awk '/^[[:digit:]]/{print $2}' input.txt
0
1
2
6
9
1.09
13
15
25
1.09
28

浮動小数点数も削除するには、論理AND演算子&&を使用して追加のパターンを追加します。

$ awk '/^[[:digit:]]/ && $0 !~ /[.]/ {print $2}' input.txt
0
1
2
6
9
13
15
25
28

または、単に否定パターンを使用してシェイクの統計情報を除外します。

awk '!/^SHAKE/ && $0 !~ /[.]/ {print $2}' input.txt 

コメント内の質問に対処するために、範囲パターン(/Pattern1/,/Pattern2/ {commands}など)をifステートメントと組み合わせることができます。範囲パターンは、範囲に適合する行に対してのみ中括弧内のコマンドを実行し、ifステートメントが追加のフィルタリングを実行できます。この特定のケースでは、次のような以前のソリューションと単純に組み合わせることができます。

$ awk '$0 == "Step Temp Enthalpy",0 { if( $0 ~ /^[[:digit:]]/ && $0 !~ /[.]/  ) print $2  }' input.txt

パターン$0 == "Step Temp Enthalpy",0は、正確な行Step Temp Enthalpyから0への処理、つまりファイルの終わりを意味します。

2

以下は、コンテンツの一致ではなく、データの構造に基づいた(おそらく)より単純なアプローチです。

  • モジュロ演算を使用して、SHAKE stats行の1つにいるかどうかをテストします
  • もしそうなら、getlineで次の行を丸lurみして先に進みます
  • そうでない場合は、2番目のフィールドを印刷します

そう

$ awk '!(NR%7) {getline; next} {print $2}' data
Temp
0
1
2
6
9
13
15


25
28
2
steeldriver