Awk 否则,梯子不得进入“;否则";当没有条件匹配时

Awk 否则,梯子不得进入“;否则";当没有条件匹配时,awk,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 {

我正在用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大师帮我找出哪里出了问题


谢谢

当您发现自己在使用任何类型的
not
运算符时,停下来想想是否可以使用正条件而不是负条件来编写代码。这将使您的代码更清晰,并避免出现双重否定的情况(例如在代码中,
if!…else!…
-实际上可能是三重否定!),这是非常难以理解的,并且可能会产生错误

另外,永远不要使用范围表达式,如
/start/,/end/
,因为它们会使琐碎的代码稍微简短一些,但如果有任何更有趣的事情需要完全重写或复制条件,请始终使用标志变量

最后,不要对变量名使用全大写,以避免与内置变量名发生冲突

因此,第1步是将所有变量的大小写改为小写,去掉所有冗余的
-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
}
看看它有多清晰和简单,我们如何只测试一次条件?现在在示例输入上运行它:

$ awk -f v2.awk file
1
1
3

当您发现自己在使用任何类型的
not
运算符时,停下来想想是否可以使用正条件而不是负条件来编写代码。这将使您的代码更清晰,并避免出现双重否定的情况(例如在代码中,
if!…else!…
-实际上可能是三重否定!),这是非常难以理解的,并且可能会产生错误

另外,永远不要使用范围表达式,如
/start/,/end/
,因为它们会使琐碎的代码稍微简短一些,但如果有任何更有趣的事情需要完全重写或复制条件,请始终使用标志变量

最后,不要对变量名使用全大写,以避免与内置变量名发生冲突

因此,第1步是将所有变量的大小写改为小写,去掉所有冗余的
-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
}
看看它有多清晰和简单,我们如何只测试一次条件?现在在示例输入上运行它:

$ awk -f v2.awk file
1
1
3

~表示“不匹配”。你想要
~
,“匹配”我花在这上面的时间,啊!非常感谢。不管你是一个多么有经验的程序员,这总是一些小而愚蠢的事情。谢谢你多给我一双眼睛!:)没问题!下次您可以通过添加print语句来查看脚本在哪里开始偏离您的预期,这将使您自己变得更容易,在本例中,当
STATS\u START
导致脚本进入
SECTION\u FINISHED
子句时。这比仅仅比较预期和实际的最终输出更能缩小问题的范围。
~表示“不匹配”。你想要
~
,“匹配”我花在这上面的时间,啊!非常感谢。不管你是一个多么有经验的程序员,这总是一些小而愚蠢的事情。谢谢你多给我一双眼睛!:)没问题!下次您可以通过添加print语句来查看脚本在哪里开始偏离您的预期,这将使您自己变得更容易,在本例中,当
STATS\u START
导致脚本进入
SECTION\u FINISHED
子句时。这就缩小了问题的范围,不仅仅是比较预期和实际的最终输出。