.txtをフィルタリングするために.awkソースファイルを作成しようとしていますが、2番目のコマンドでmax変数を使用する方法を知りたいです。
BEGIN {max1=0}
2つのパターン(0と1)の間の最大値$ 4を見つけて変数に設定します。
{if ($4>0 && $4<1)
max1=$4
else if ($4==1)
max=max1}
END {print max}
/Nodes/ {f=1} /EndNodes/ {f=0} #Gives lines after Nodes and before EndNodes
{if ($2+0>=0 && $3+0==0 && max==$4) #Filters the given lines between Nodes and EndNodes
{print $1}}
私の考えでは、max変数を定義した後、最初からプログラムを実行する必要があるようです。 (2番目のコマンドと同じ行を使用するためです。)
予想される出力は次のとおりです。20、31、32
入力する
$Nodes
34
1 0.0000000E+000 0.0000000E+000 0.0000000E+000
2 6.0000000E-003 0.0000000E+000 0.0000000E+000
3 0.0000000E+000 6.0000000E-003 0.0000000E+000
4 -6.0000000E-003 0.0000000E+000 0.0000000E+000
5 0.0000000E+000 -6.0000000E-003 0.0000000E+000
6 2.1213203E-003 2.1213203E-003 0.0000000E+000
7 -2.1213203E-003 2.1213203E-003 0.0000000E+000
8 -2.1213203E-003 -2.1213203E-003 0.0000000E+000
9 2.1213203E-003 -2.1213203E-003 0.0000000E+000
10 4.2426407E-003 4.2426407E-003 0.0000000E+000
11 -4.2426407E-003 4.2426407E-003 0.0000000E+000
12 -4.2426407E-003 -4.2426407E-003 0.0000000E+000
13 4.2426407E-003 -4.2426407E-003 0.0000000E+000
14 2.1213203E-003 0.0000000E+000 0.0000000E+000
15 0.0000000E+000 2.1213203E-003 0.0000000E+000
16 -2.1213203E-003 0.0000000E+000 0.0000000E+000
17 0.0000000E+000 -2.1213203E-003 0.0000000E+000
18 0.0000000E+000 2.1213203E-003 6.0000000E-003
19 0.0000000E+000 6.0000000E-003 6.0000000E-003
20 0.0000000E+000 0.0000000E+000 6.0000000E-003
21 -4.2426407E-003 4.2426407E-003 6.0000000E-003
22 -2.1213203E-003 2.1213203E-003 6.0000000E-003
23 -6.0000000E-003 0.0000000E+000 6.0000000E-003
24 -2.1213203E-003 0.0000000E+000 6.0000000E-003
25 -4.2426407E-003 -4.2426407E-003 6.0000000E-003
26 -2.1213203E-003 -2.1213203E-003 6.0000000E-003
27 0.0000000E+000 -6.0000000E-003 6.0000000E-003
28 0.0000000E+000 -2.1213203E-003 6.0000000E-003
29 4.2426407E-003 -4.2426407E-003 6.0000000E-003
30 2.1213203E-003 -2.1213203E-003 6.0000000E-003
31 6.0000000E-003 0.0000000E+000 6.0000000E-003
32 2.1213203E-003 0.0000000E+000 6.0000000E-003
33 4.2426407E-003 4.2426407E-003 6.0000000E-003
34 2.1213203E-003 2.1213203E-003 6.0000000E-003
$EndNodes
$Elements
#And some more data
$EndElements
答え1
ワンタイムソリューションは次のとおりです。
/Nodes/ { read = 1 }
/EndNodes/ { read = 0 }
!read { next }
NF == 4 { n = $1; x = $2; y = $3; z = $4 }
z > max { delete set; i = 1; max = z }
x >= 0 && y == 0 && z == max { set[i++] = n }
END { for (i in set) { print set[i] } }
このread
変数は、現在のレコードに対して操作を実行する必要があるかどうかを決定します。 1の場合はこれを行います。
現在の入力に興味がない場合、3番目のブロックは現在の入力を破棄し、上から次のレコードを処理し続けます。
ブロック4は4つの便利な変数、n
およびx
を設定しますy
。他よりz
読みやすいです。$1
ブロック5では、配列を削除しますset
。このset
配列は、条件を満たすこれまでに見つかったすべてのノード番号の集まりです。新しい最大値が見つかると、このブロックが実行されるため、z
以前に見つかったすべてのノードは無効になります。また、新しい最大値(max
)を保存します。変数はi
単に配列のインデックスです(デフォルトではカウンタ)。最大値が見つからない場合、max
初期化されていない値はテストでゼロとして扱われます。
条件を満たすノードが見つかると、6番目のブロックが実行されます。ノード番号は配列に格納さset
れ、インクリメントされi
ます。
set
最後に、配列を繰り返してその内容を印刷します。
GNUで実行した結果はawk
次のとおりです。
20
31
32
BSDawk
とmawk
OpenBSD で実行すると、リストは逆順に生成されます。
答え2
アッ解決策:
get_max_nodes.awkスクリプト:
#!/bin/awk -f
BEGIN{ max=0 }
NR==FNR{ # processing the 1st input file
if ($4~/^[0-9]/) { # if the 4th field is a number
if($4+0 > max) max=$4+0 # capturing maximal number
}
next
}
{ # processing the 2nd input file (same file)
if ($4~/^[0-9]/ && $2+0>=0 && $3+0==0 && $4+0==max) {
print $1
}
}
使用法:
awk -f get_max_nodes.awk input.txt input.txt
出力:
20
31
32
答え3
コメントするには評判が不足して回答をするようになりました。私の最初のコメントは、awkが間違いの数学を実行するのに最適なツールではないということです。文字列と整数が良いです。
awkに関するその他の点:BEGIN段落は入力から行を読む前に発生します。 END 段落はすべての行を読んだ後に発生します。
注:awkは、コードにレコード/フィールドを保存する手順を実行しない限り、現在の入力ライン/レコード以外のものを保存または気にしません。これはBEGINとENDの間に発生する必要があります。
この段落間のコードは変数の設定/リセットのみを行い、その値には何もしません。デフォルトでは、入力ファイルを-1で終わり、出力をパイプして同様の結果を得ることができます。
あなたの意図は、最大または最大1を見つけるために列4の数字をテストし、列4にこの最大値が含まれている場合は列1のみを印刷してから列2と3を正常にテストすることです。ファイルの最後の行にのみ興味がある場合を除き、このロジックをENDの前に移動する必要があります。
awkでは、各入力行が(デフォルトでは)各条件と比較されることに注意してください。条件が true の場合は、ジョブまたはジョブのリストを実行します。同じ行にジョブをトリガーする複数の条件がある可能性があります。
最初の印象は、プロセスを再評価する必要があるということです。重要度を決定し、それに応じて行動する。たとえば、私にとって最初の重要な順序は、入力ファイルの2つのフラグ間のデータでのみ機能します。次に、4つのフィールドのそれぞれの実数が意味を失うことなく、整数(または文字列)に変換(または処理)できるかどうかを決定します。実際のデータ自体は変更する必要はなく、コード内の表現のみを変更できます。これを再変換できますが、元の数字の精度を失う可能性があります。最後に、後で処理するために並べ替えられていない任意のデータ全体/すべてのデータを保存するか、各出力行をすぐに提供するかを選択します。
次のメタ例は、より効率的に実行できます。解析を開始する時間かどうかを示すフラグで始まります。 $0 ~= /Nodes/ を見たことがありますか?開始= 0。 $0 ~= /EndNodes/ line, stop=0 をテストして、データの解析を停止するタイミングを知るために準備することもできます。データを保存するには、おそらくcount = 0というカウンタが必要です。
BEGIN {
start=0
stop=0
count=0
max=0
}
/EndNodes/ {
stop=1
}
/Nodes/ {
start=1
}
NF==4 {
if (start==1 && stop==0) {
count++
column1[count]=$1
column2[count]=substr($2,1,index($2,".")-1)
column3[count]=substr($3,1,index($3,".")-1)
column4[count]=substr($4,1,index($4,".")-1)
}
}
# Now print column1 if column2 is non-negative and column3=0 and column4=max
# In the first loop through the array/list, find max
END {
for (loop=1;loop<=count;loop++) {
if (column4[loop]>max) {
max=column4[loop]
}
}
for (loop=1;loop<=count;loop++) {
if (column4[loop]==max && column3[loop]==0 && column2[loop]>=0) {
print column1[loop]
}
}
}
作成したとおり、出力は次のようになります。
20
31
32