awk 中的 BEGIN 会产生意想不到的行为

BEGIN in awk yields unexpected behavior

最近在学习awk。我发现我使用 BEGIN{} 得到的结果对我来说是非常出乎意料的。让我们看看下面这个例子:

1. echo "Create" | awk 'IGNORECASE = 1;/create/;'  this would print out `Create` : 

2. echo "Create" | awk 'BEGIN{IGNORECASE = 1};/create/;' returns nothing 

据我所知,BEGIN{} 表示:

Awk will execute the action(s) specified in BEGIN once before any input lines are read.

我想知道为什么第二个命令returns没有。

IGNORECASE是一个 GNU 扩展,您没有使用 GNU awk,所以

  1. BEGIN{IGNORECASE=1} 设置一个未使用的变量,就像 BEGIN{FOO=1} 一样,所以它后面的 /create/ 仍然不会匹配 Create.
  2. IGNORECASE=1; 在任何操作块之外设置一个变量,然后测试设置该变量的结果,现在为 1/true,因此在打印当前条件的情况下调用默认操作线。后面的/create/还是匹配不到Create.

看:

$ echo foo | awk 'IGNORECASE=1; /bar/'
foo

$ echo foo | awk 'whatever=1; /bar/'
foo

$ echo foo | awk 'whatever=1'
foo

要像您尝试的那样对小写正则表达式进行不区分大小写的匹配,将在任何 awk 中执行以下操作:

$ echo 'Create' | awk 'tolower([=11=]) ~ /create/'
Create

获取 Arnold Robbins 撰写的《Effective AWK Programming》第 5 版并阅读前几页以了解 AWK 语法。