如果没有条件匹配,则if-else阶梯不输入“ else”

时间:2019-05-10 17:29:22

标签: awk

我正在用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专家都可以帮助我找出问题所在吗?

谢谢!

1 个答案:

答案 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
}