AWK問題:指定された/ pattern /の後の3行目から始めて、N行を印刷します。

AWK問題:指定された/ pattern /の後の3行目から始めて、N行を印刷します。

次のセクションを含む巨大なファイルを作成しています。

~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~ Gradients ~~~~~~~~
~~~~~~~~~ x y z ~~~~~~~~~~
~ ~
~ H         1      0.00781      0.00108      0.00038 ~
~ H         2      0.01271     -0.01507      0.02839 ~
~ C         1     -0.05015     -0.01803      0.01588 ~
~ O         1      0.01733      0.03089     -0.04611 ~
~ O         2      0.01230      0.00114      0.00147 ~
~ ~
~~~~~~~~~~~~~~~~~~~~~~~~

次の数字(xyz)を抽出する必要があります。

0.00781      0.00108      0.00038
0.01271     -0.01507      0.02839
-0.05015     -0.01803      0.01588
0.01733      0.03089     -0.04611 
0.01230      0.00114      0.00147

私は次のスクリプトを書いた。

awk '/z ~/ {for(i=1; i<=6; i++) {getline; print $4, $5, $6}}' filename

しかし、「~~」行のため空の行が出てきます。

つまり、/z ~/パターンが見つかるたびに別の行(パターン+1)をスキップして、他の5行(パターン+2+3+4+5+6)の内容だけを印刷したいのです。もちろん繰り返し(数十万回)が必要です。

答え1

アッ解決策:

awk '/z ~/{ n=NR+2 }n && n<=NR && NR<(n+5){ print $4,$5,$6 }' file | column -t

出力:

0.00781   0.00108   0.00038
0.01271   -0.01507  0.02839
-0.05015  -0.01803  0.01588
0.01733   0.03089   -0.04611
0.01230   0.00114   0.00147

  • NR- 現在のレコード数

  • n=NR+2-nモデルラインの後の「スタート」ライン番号を示します。

答え2

最も簡単な解決策は、1つを追加してgetline6行ではなく5行を取得することです。

$ awk '/z ~/ {getline;for(i=1; i<=5; i++) {getline; print $4, $5, $6}}' file
0.00781 0.00108 0.00038
0.01271 -0.01507 0.02839
-0.05015 -0.01803 0.01588
0.01733 0.03089 -0.04611
0.01230 0.00114 0.00147

しかし、個人的に私は少し異なる方法で仕事をします。

$ awk '/z ~/{f=2;} /~ ~/{f--}; (f==1 && NF>5){print $4, $5, $6} ' file
0.00781 0.00108 0.00038
0.01271 -0.01507 0.02839
-0.05015 -0.01803 0.01588
0.01733 0.03089 -0.04611
0.01230 0.00114 0.00147

ここでのアイデアは、一致する行にフラグ(変数)を設定し、一致する行が見つかるたびにfその値を1ずつ減らすことです。次に、フィールド4、5、6を次の行にのみ印刷します。2z ~~ ~f1 そしてフィールドが5つ以上あります。

どちらの例でも、きれいな印刷を得るには、次の方法を使用するか、-vOFS="\t"より良い方法を使用できますprintf

$ awk '/z ~/{f=2;} /~ ~/{f--}; (f==1 && NF>5){printf "%10s%10s%10s\n", $4, $5, $6} ' file
   0.00781   0.00108   0.00038
   0.01271  -0.01507   0.02839
  -0.05015  -0.01803   0.01588
   0.01733   0.03089  -0.04611
   0.01230   0.00114   0.00147

答え3

布材

  1. まず、範囲を線で分離します/~ ~/。外部の内容はすべて削除されます。
  2. 範囲異常値自体も削除されます。
  3. これで処理する正しい行ができました。この行では、\n4番目のフィールドの先頭にマーカーを配置し、6番目のフィールドの最後に別のマーカーを配置します。
  4. 最後に、これらのタグの外側のすべての項目を削除して、4番目、5番目、6番目のフィールドとそれらの間のスペース(未修正)のみを残します。

sed -ne '
   /~ ~/,//!d
   //d
   s/[^[:space:]]\{1,\}/&\n/6
   s/[^[:space:]]\{1,\}/\n&/4
   s/.*\n\(.*\)\n.*/\1/p
' yourfile

結果

0.00781      0.00108      0.00038
0.01271     -0.01507      0.02839
-0.05015     -0.01803      0.01588
0.01733      0.03089     -0.04611
0.01230      0.00114      0.00147

答え4

このラインのマッチングに関する限り、パターンは十分で/^~ [A-Z]/あり、各印刷に対応するフィールド4、5及び6が存在する。

awkのバージョンは次のとおりです。

$ awk '/^~ [A-Z]/{printf("%-8s\t%-8s\t%-8s\n",$4,$5,$6)}' input.txt
0.00781     0.00108     0.00038 
0.01271     -0.01507    0.02839 
-0.05015    -0.01803    0.01588 
0.01733     0.03089     -0.04611
0.01230     0.00114     0.00147 

そして、同じ内容をPerlに翻訳すると、次のようになります。

$ perl -ane 'printf("%-8s\t%-8s\t%-8s\n",$F[3],$F[4],$F[5]) if /^~ [A-Z]/' input.txt                                     
0.00781     0.00108     0.00038 
0.01271     -0.01507    0.02839 
-0.05015    -0.01803    0.01588 
0.01733     0.03089     -0.04611
0.01230     0.00114     0.00147 

ここでは、適切な書式設定のために左揃えprintf()フラグと一緒に関数を使用します%-8s

別のアプローチは、必要な数を浮動小数点数として扱い、%f代わりに指定子を使用することです%-8s。ただし、これによりいくつかの数値に0が追加されます。

関連情報