我正在用Ubuntu仿真器编写第一个大型awk脚本,但遇到一个奇怪的问题-我的代码不会在下面的if-else阶梯中输入“ else”。
BEGIN {
SECTION_RECORD=0;
}
/STATS_START/,/STATS_END/ {
if ($0 !~ /STATS_START/) { SECTION_PRESENT="1"; }
else if ($0 !~ /STATS_END/) { SECTION_FINISHED="1"; }
else {
SECTION_RECORD=SECTION_RECORD+1;
}
}
END {
print SECTION_PRESENT;
print SECTION_FINISHED;
print SECTION_RECORD;
}
我正在读取以下输入文件。
=== STATS_START ===
this is a stat
this is another
a third stat
=== STATS_END ===
由于该部分以3条记录开始和结束,因此我希望该程序的输出为:
1
1
3
但是,我得到了:
1
1
0
我已经通过打印声明(为清楚起见,从本示例中删除了该声明)确认从未输入过“ else”。我使用“ --lint”和“ --posix”选项运行了该脚本,并且该脚本在运行时没有警告或错误。
我真的在这里挠头。该代码似乎是正确的,但是我猜想我在GNU文档中错过了一些有关awk的原因。请问任何awk专家都可以帮助我找出问题所在吗?
谢谢!
答案 0 :(得分:0)
每当您发现使用任何类型的pre-request script
运算符时,请停止并思考,如果您可以使用正数而不是负数的条件编写代码。这将使您的代码更清晰,并避免您最终遇到双重否定的情况(例如在您的代码中,not
-可能实际上是三次否定的结果!),这很难理解并且很可能会产生错误
也不要使用诸如if ! ... else ! ...
之类的范围表达式,因为它们会使平凡的代码变得更加简短,但是对于最有趣的东西,则需要完整的重写或重复条件,而请始终使用标志变量。
最后,不要将所有大写字母用作变量名,以避免与内置变量名冲突。
因此,第1步是使所有变量变为小写,摆脱所有多余的/start/,/end/
,并使用GNU awks ;
对其进行格式化以使其可读性更好地打印代码:
-o-
现在,我们可以不使用范围表达式来编写它:
$ awk -o- -f tst.awk > v1.awk
$ cat v1.awk
BEGIN {
section_record = 0
}
/STATS_START/, /STATS_END/ {
if ($0 !~ /STATS_START/) {
section_present = "1"
} else if ($0 !~ /STATS_END/) {
section_finished = "1"
} else {
section_record = section_record + 1
}
}
END {
print section_present
print section_finished
print section_record
}
看看它更清晰,更简单,以及我们如何仅对条件进行一次测试?现在在您的示例输入上运行它:
$ cat v2.awk
BEGIN {
section_record = 0
}
/STATS_END/ {
in_section = 0
section_finished++
}
in_section {
section_record++
}
/STATS_START/ {
in_section = 1
section_present++
}
END {
print section_present
print section_finished
print section_record
}