2つのパターン(0と1)の間の最大値$ 4を見つけて変数に設定します。

2つのパターン(0と1)の間の最大値$ 4を見つけて変数に設定します。

.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

BSDawkmawkOpenBSD で実行すると、リストは逆順に生成されます。

答え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

関連情報