AWKスクリプトのwhile関数に関する問題

AWKスクリプトのwhile関数に関する問題

私はシミュレーションで評価ファイルを処理するために使用する見苦しいスクリプトを持っています。それはひどいようです。いいえ、私はコーダーではなく、通常は動作しますが、現在は動作しません。

明らかに、スクリプトは通常複数の入力ファイルを繰り返し、私のMacとシミュレーションを実行しているクラスタで動作します。 Ubuntuサーバーを実行しているVPSで実行しようとすると、奇妙な出力が生成されます。この問題を解決する方法がわかりません。

完全なスクリプトは次のとおりです。

#!/usr/bin/awk -f
FNR==1 && NR!=1 { endfile(); avgLT=totFrames=avgLTsq=avgFramessq=denom=0 }
FNR==1 { out1="analLT_"FILENAME; out2="sumLT_"FILENAME; out3="reportLT.txt"; print "-> Input file is: "FILENAME >> out3; next
       }
FNR==1 { next }

{
   avgLT+=$4; totFrames+=$5; ++denom;
   printf "%10.4f %10.1f\n",$4,$5 > out1
  }

END { endfile() }
function endfile()
{
  x="\nNO DATA POINTS IN INPUT => NO HYDROGEN BONDS DETECTED!"
  if (avgLT==0 && denom==0) {
    print x > out1; print x > out2; print x"\n\n----------------------------------------\n" >> out3;
    close(out1); close(out2); close(out3); return
  }
  if (avgLT>0) {
    avgAvgLT=avgLT/denom
    avgFrames=totFrames/denom
    while ((getline<out1)>0) {
      avgLTsq+=(($1-avgAvgLT)^2)
      avgFramessq+=(($2-avgFrames)^2)
    }
  close(out1)
    printf "\n   Summary data for hbond lifetime analysis:\n\n" > out2
    printf "   Summed Avg Lifetime:    %10.4f\n",avgLT > out2
    printf "   Average Lifetime:       %10.4f\n",avgAvgLT > out2
    printf "      Summed Frames:  %10.0f\n",totFrames > out2
    printf "      Average Frames:      %10.4f\n",avgFrames > out2
    printf "\n   Summary data for hbond lifetime analysis:\n\n" >> out3
    printf "   Summed Avg Lifetime:    %10.4f\n",avgLT >> out3
    printf "   Average Lifetime:       %10.4f\n",avgAvgLT >> out3
    printf "      Summed Frames:  %10.0f\n",totFrames >> out3
    printf "      Average Frames:      %10.4f\n",avgFrames >> out3

    if (denom>1) {
      sd_avgLT=sqrt(avgLTsq/(denom-1)); semAvgLT=(sd_avgLT/(sqrt(denom))); sd_totFrames=sqrt(avgFramessq/(denom-1)); semTotFrames=(sd_totFrames/(sqrt(denom)))
      printf "\n   SD lifetime:            %10.4f\n",sd_avgLT > out2
      printf "   SEM lifetime:           %10.4f\n",semAvgLT > out2
      printf "      SD Frames:           %10.4f\n",sd_totFrames > out2
      printf "      SEM Frames:          %10.4f\n\n",semTotFrames > out2
      printf "\n   SD lifetime:            %10.4f\n",sd_avgLT >> out3
      printf "   SEM lifetime:           %10.4f\n",semAvgLT >> out3
      printf "      SD Frames:           %10.4f\n",sd_totFrames > out3
      printf "      SEM Frames:          %10.4f\n\n",semTotFrames > out3
    } if (denom>1 && denom!=2) {print "----------------------------------------\n" >> out3 }
      if (denom==1) { print "   Single HBOND event, no SD or SEM calculation possible!" > out2;
             print "\n   Single HBOND event, no SD or SEM calculation possible!\n\n----------------------------------------\n" >> out3
           }
      if (denom==2) { print "\n   2 Hydrogen bond events found! No proper SD or SEM!" > out2;
             print "   2 Hydrogen bond events found! No proper SD or SEM!\n\n----------------------------------------\n" >> out3
           }
}
  close(out3)
  close(out2)
}

5列入力ファイルをインポートして2列を処理し、後で処理するために同じ列を別のファイルに入れます(out1)。その後、いくつかの統計を計算するためにファイルを処理する必要があります。しかし、これはVPSでは発生せず、私が得た値はすべて0.0000です。

問題はwhile関数にあるようです。

while ((getline<out1)>0) {
      avgLTsq+=(($1-avgAvgLT)^2)
      avgFramessq+=(($2-avgFrames)^2)
    }

スクリプトの最後に内容がファイルに出力されると、計算された合計と平均(、、、avgLT平均avgAvgLT)の合理的な値が得られるようです。統計セクション(、および)に達すると、すべての値は元の値ではなく0.0000ですが、両方の項目に印刷されます。totFramesavgFramessd_avgLTsemAvgLTsd_totFramessemTotFramesout2out3

out1「math」は、ファイルに対して個別にコマンドを実行できるようです。

awk ' BEGIN { avgAvgLT=1.4264 } { avgLTsq+=(($1-avgAvgLT)^2) } END { print avgLTsq }' analLT_multiple.out
awk ' BEGIN { avgFrames=4.4831 } { avgFramessq+=(($2-avgFrames)^2) } END { print avgFramessq }' analLT_multiple.out
awk ' BEGIN { avgLTsq=30.3478; denom=89 } { sd_avgLT=sqrt(avgLTsq/(denom-1)) } END { print sd_avgLT }' analLT_multiple.out
awk ' BEGIN { sd_avgLT=0.587249; denom=89 } {semAvgLT=(sd_avgLT/(sqrt(denom))) }  END { print semAvgLT }' analLT_multiple.out
awk ' BEGIN { avgFramessq=2040.22; denom=89 } { sd_totFrames=sqrt(avgFramessq/(denom-1)) } END { print sd_totFrames }' analLT_multiple.out
awk ' BEGIN { sd_totFrames=4.81501; denom=89 } { semTotFrames=(sd_totFrames/(sqrt(denom))) } END { print semTotFrames }' analLT_multiple.out

ゼロ以外の値を提供することで合理的に見えますが、スクリプトはすべての値を0.0000として提供します。また、複数のファイルを実行したときにスクリプトの変数値を印刷してみましたが、、、、およびすべて0または空の値を返しましdenomたが、変数はまだ機能していました。sd_avgLTsemAvgLTsd_totFramessemTotFrames

私の「結論」(ここで推測だと言いたい)は、前に述べたように、while関数に問題があるということです。何かはわかりませんが。

Pastebinにサンプル入力ファイルを入れました。https://pastebin.com/JsuTz0mD スクリプトを直接実行してみたい場合。

私のVPSシステムでこのスクリプトを動作させるための入力/フィードバックまたはソリューションを提供していただきありがとうございます。

ベストアンサー1

ファイルに書き込むときにファイルに書き込まれるデータをフラッシュしない(GNUまたは)、書き込み用に開いたままにしておくawkファイルハンドルから何かを読み取っています。これは、このファイルのデータをチャンクで読み取ったときにデータが読み込まれないことを意味します。 BSDの実装にはこの問題はないようで、コードはOpenBSDやmacOSなどで期待どおりに動作します。awkmawkout1awkENDawk

回避策は簡単です。無条件ブロックでclose(out1)使用してください。END今後現在はそれをgetline閉じます。後ろにそれを読んでください。

>また、との一貫性を維持することをお勧めします>>。私はあなたが>このコードを完全に使用できると信じています。

おすすめ記事