次のセクションを含む巨大なファイルを作成しています。
~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~ 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つを追加してgetline
6行ではなく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を次の行にのみ印刷します。2
z ~
~ ~
f
1
そしてフィールドが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
布材
- まず、範囲を線で分離します
/~ ~/
。外部の内容はすべて削除されます。 - 範囲異常値自体も削除されます。
- これで処理する正しい行ができました。この行では、
\n
4番目のフィールドの先頭にマーカーを配置し、6番目のフィールドの最後に別のマーカーを配置します。 - 最後に、これらのタグの外側のすべての項目を削除して、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が追加されます。