저는 시뮬레이션에서 평가 파일을 처리하는 데 사용하는 보기 흉한 스크립트를 가지고 있습니다. 그것은 끔찍해 보입니다. 아니요, 저는 코더가 아니며 일반적으로 작동하지만 현재는 작동하지 않습니다.
명확히 말하면 스크립트는 일반적으로 여러 입력 파일을 반복하며 내 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이지만 두 항목 모두에 인쇄됩니다.totFrames
avgFrames
sd_avgLT
semAvgLT
sd_totFrames
semTotFrames
out2
out3
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이 아닌 값을 제공하여 합리적으로 보이지만 스크립트는 모든 값을 0.0000으로 제공합니다. 또한 여러 파일을 실행할 때 스크립트의 변수 값을 인쇄해 보았는데, , , 및 모두 0 또는 빈 값을 반환 denom
했지만 변수는 여전히 작동했습니다.sd_avgLT
semAvgLT
sd_totFrames
semTotFrames
내 "결론"(여기서 추측이라고 말하고 싶습니다)은 이전에 말했듯이 while 함수에 문제가 있다는 것입니다. 비록 무엇인지는 모르겠지만요.
Pastebin에 샘플 입력 파일을 넣었습니다.https://pastebin.com/JsuTz0mD 스크립트를 직접 실행해 보고 싶다면.
내 VPS 시스템에서 이 스크립트가 작동하도록 하기 위한 입력/피드백 또는 솔루션을 제공해 주시면 대단히 감사하겠습니다.
답변1
파일에 쓸 때 파일에 기록되는 데이터를 플러시하지 않거나(GNU 또는) 쓰기 awk
위해 열어 두는 파일 핸들에서 무엇이든 읽고 있습니다. 이는 이 파일의 데이터를 청크로 읽을 때 데이터가 읽히지 않음을 의미합니다. BSD 구현에는 이 문제가 없는 것 같고 코드는 OpenBSD 및 macOS 등에서 예상대로 작동합니다.awk
mawk
out1
awk
END
awk
해결 방법은 간단합니다. 무조건 블록에서 close(out1)
사용하세요 .END
앞으로현재는 그것을 getline
닫습니다.뒤쪽에그것을 읽어보세요.
>
또한 및 의 일관성을 유지하는 것이 좋습니다 >>
. 나는 당신이 >
이 코드를 전체적으로 사용할 수 있다고 믿습니다.
답변2
@Kusalananda가 이미 무엇이 잘못되었는지 말했기 때문에 이것은 대답이 아닙니다. 하지만 스크립트를 약간 정리하여 읽기 쉽게 만들고 코드 중복을 줄이도록 하겠습니다.
FNR == 1 {
if ( NR != 1 ) {
endfile()
}
avgLT = totFrames = denom = 0
out1 = "analLT_" FILENAME
out2 = "sumLT_" FILENAME
out3 = "reportLT.txt"
print "-> Input file is: " FILENAME > out3
next
}
{
avgLT += $4
totFrames += $5
++denom
printf "%10.4f %10.1f\n", $4, $5 > out1
}
END {
endfile()
}
function endfile( x, avgAvgLT, avgFrames, sd_avgLT,
semAvgLT, sd_totFrames, semTotFrames )
{
if (avgLT == 0 && denom == 0 ) {
x = "\nNO DATA POINTS IN INPUT => NO HYDROGEN BONDS DETECTED!"
print x > out1
print x > out2
print x > out3
}
else if (avgLT > 0) {
avgAvgLT = avgLT / denom
avgFrames = totFrames / denom
close(out1)
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) {
x = " Single HBOND event, no SD or SEM calculation possible!"
print x > out2
print "" > out3
print x > out3
}
else 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 == 2) {
x = " 2 Hydrogen bond events found! No proper SD or SEM!"
print "" > out2
print x > out2
print x > out3
}
}
print "\n\n----------------------------------------\n" > out3
close(out1)
close(out2)
close(out3)
}
out1의 while getline 루프는 스크립트 본문에 out1을 작성하는 대신 배열에 데이터를 저장할 수 있으므로 실제로 필요하지 않습니다. 예를 들면 다음과 같습니다.
FNR == 1 {
if ( NR != 1 ) {
endfile()
}
avgLT = totFrames = denom = 0
out1 = "analLT_" FILENAME
out2 = "sumLT_" FILENAME
out3 = "reportLT.txt"
print "-> Input file is: " FILENAME > out3
next
}
{
avgLT += $4
totFrames += $5
++denom
fnr2avgLT[FNR] = avgLT
fnr2totFrames[FNR] = totFrames
}
END {
endfile()
}
function endfile( i, x, avgAvgLT, avgFrames, sd_avgLT,
semAvgLT, sd_totFrames, semTotFrames )
{
if (avgLT == 0 && denom == 0 ) {
x = "\nNO DATA POINTS IN INPUT => NO HYDROGEN BONDS DETECTED!"
print x > out1
print x > out2
print x > out3
}
else if (avgLT > 0) {
avgAvgLT = avgLT / denom
avgFrames = totFrames / denom
for (i=1; i<=FNR; i++) {
avgLT = fnr2avgLT[i]
totFrames = fnr2totFrames[i]
printf "%10.4f %10.1f\n", avgLT, totFrames > out1
avgLTsq += ((avgLT - avgAvgLT) ^ 2)
avgFramessq += ((totFrames - avgFrames) ^ 2)
}
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) {
x = " Single HBOND event, no SD or SEM calculation possible!"
print x > out2
print "" > out3
print x > out3
}
else 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 == 2) {
x = " 2 Hydrogen bond events found! No proper SD or SEM!"
print "" > out2
print x > out2
print x > out3
}
}
print "\n\n----------------------------------------\n" > out3
close(out1)
close(out2)
close(out3)
}
물론 테스트할 샘플 입력/출력을 제공하지 않았기 때문에 위의 모든 항목은 테스트되지 않았지만 모든 버그를 쉽게 발견하고 수정할 수 있기를 바랍니다.