我有一系列目录
079/af3
100/af4
120/af3
.
.
.
每个???/af?
目录都包含一个非常长的文件results.stdout
。靠近此文件的末尾,可以找到字符串
Normal termination: iterations complete!
如果af3(resp.af4)中的计算成功,则在文件中写入一条或多条错误消息。为了避免必须手动检查每个文件,我正在编写一个生成摘要文件的脚本:
Massflow af3 af4
079 Success Failure
100 Failure Success
120 Success Success
. . .
. . .
到目前为止,我已经能够做到以下几点了:
#!/bin/bash
strlen="9" # want to keep the format flexible, instead than hardcode it
format0="%"$strlen"s %"$strlen"s %"$strlen"s\n"
# write the header of file summary
awk -v format="$format0" ' BEGIN { printf format, "Massflow", "af3", "af4"
} ' >> summary
for dir in ??? # loop on all the directories
do
for j in 3 4 # loop on the two subdirs
do
result[$j]=$(tac $dir/af$j/results.stdout | awk '
/TACOMA:- Normal termination: iterations complete!/ {success = 1; exit}
END { if (success == 1)
print "Success"
else
print "Failure"
}')
done
done
exit
但是,我不知道如何编写摘要文件...我想将result
数组传递给另一个awk程序,但是awk不接受数组变量。有什么建议?如果您认为我的编程风格,工具选择或两者都很糟糕,请随意更改方法甚至工具:)
答案 0 :(得分:2)
循环时我只会printf
结果:
printf 'Massflow af3 af4\n'
for dir in $(find -maxdepth 1 -type d) # loop on all the directories
do
printf ' %d ' "$(printf '%s' "$dir" | sed -e 's/[^0-9]//g')"
for j in 3 4 # loop on the two subdirs
do
result[$j]=$(tac $dir/af$j/tacoma.stdout | awk '
/TACOMA:- Normal termination: iterations complete!/ {success = 1; exit}
END { if (success == 1)
print "Success"
else
print "Failure"
}')
printf ' %s' "$result[j]"
done
printf '\n'
done
答案 1 :(得分:2)
首先,不要使用tac,因为反转整个文件没有任何好处。只需将文件提供给awk。
您可以省略第二个for循环并保存两个结果并在之后打印:
for dir in ??? # loop on all the directories
do
for j in 3 4; do
af[$j]=$(awk '/TACOMA:- Normal termination: iterations complete!/ {success = 1; exit}
END { if (success == 1)
print "Success"
else
print "Failure"
}' $dir/af$j/results.stdout)
done
awk -v format="$format0" "BEGIN { printf format, \"$dir\", \"${af[3]}\", \"${af[4]}\"; } " >> summary
done
来自bash
的@EdMorton只有awk
:
for dir in ??? # loop on all the directories
do
for j in 3 4; do
if grep -q "TACOMA:- Normal termination: iterations complete!" "$dir/af$j/results.stdout"; then
af[$j]="Success"
else
af[$j]="Failure"
fi
done
printf "$format0" "$dir" "${af[3]}" "${af[4]}" >> summary
done
答案 2 :(得分:2)
以下是查看问题的另一种方法:使用grep
代替awk
,并使用column
格式化输出。
isSuccess() {
if tac "$1" | grep -q 'Normal termination: iterations complete'; then
echo Success
else
echo Failure
fi
}
{
echo Massflow af3 af4
for dir in ???; do
echo "$dir" $(isSuccess "$dir/af3/results.stdout") $(isSuccess "$dir/af4/results.stdout")
done
} | column -t
答案 3 :(得分:1)
首先使用find或循环或任何你喜欢的方式构建输出文件列表,然后将整个列表传递给awk,例如
for dirName in ???
do
for subName in af3 af4
do
files="$files $dirName/$subName/results.stdout"
done
done
awk '
FNR == 1 {
split(FILENAME,dfA,"/")
dirName = dfA[1]
subName = dfA[2]
dirNames[dirName]
subNames[subName]
}
/Normal termination: iterations complete!/ {
succ[dirName,subName]
}
END {
printf "Massflow"
for (subName in subNames) {
printf "\t%s",subName
}
print ""
for (dirName in dirNames) {
printf "%s", dirName
for (subName in subNames) {
printf "\t%s", ( (dirName,subName) in succ ? "Success" : "Failure" )
}
print ""
}
}
' $files
请注意,我最后没有引用$ files,因此它会针对您的示例进行正确扩展。我只是编辑了我的答案,因为我看到目录结构是dir / subdir / results.stdout而不是dir / file,正如我初想的那样。
@ DeltaIV的resuest评论版
for dirName in ???
do
for subName in af3 af4
do
files="$files $dirName/$subName/results.stdout"
done
done
awk '
# FNR == 1 is true at the first line of each input file
FNR == 1 {
split(FILENAME,dfA,"/")
dirName = dfA[1]
subName = dfA[2]
# Use array dirNames as the set of all top level directory names
# and array subNames as the set of all sub-directory names so later
# we can loop through them all to produce output.
dirNames[dirName]
subNames[subName]
}
# Check if the current line of the current input file contains the
# success indication text.
/Normal termination: iterations complete!/ {
# The success indication text was found in the current file so
# updated array succ which is the set of all dirName/SubName
# pairs that had the success indication in their results file.
succ[dirName,subName]
}
# "END" is true after all input files have been processed.
END {
# Print the header line consisting of Massflow followed by the
# sub-directory names
printf "Massflow"
for (subName in subNames) {
printf "\t%s",subName
}
print ""
# Loop through the set of dirNames so you get one per row
# and for each dirName process all sub-directory names
for (dirName in dirNames) {
printf "%s", dirName
# Loop through the set of subNames and process each one
# as a new tab-separated column of output
for (subName in subNames) {
# If the current dirName/subName combination is in the succ
# set then print "Success", otherwise print "Failure".
printf "\t%s", ( (dirName,subName) in succ ? "Success" : "Failure" )
}
# Move down to the next row of output.
print ""
}
}
' $files