-2

Recently, I am learning awk. I found that the result I get using BEGIN{} is quite unexpected to me. Let's see this example below:

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

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

As fas as I know, BEGIN{} means:

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

I would like to know why the second command returns nothing.

TylerP
  • 9,600
  • 4
  • 39
  • 43
Pro_gram_mer
  • 749
  • 3
  • 7
  • 20
  • 2
    `echo "Create" | awk 'BEGIN{IGNORECASE = 1};/create/;'` once works for me. What's your `awk` version? – RavinderSingh13 Sep 27 '21 at 06:46
  • My bet: you are under macOS and you use the super old version of awk that comes with it. I think `IGNORECASE` is a GNU awk extension. While this macOS super old version of awk is a BSD awk, if I remember well. So, how it was implemented in the 2007 BSD awk, is difficult to find out. – Renaud Pacalet Sep 27 '21 at 07:48
  • 1
    Does this answer your question? [ignorecase in AWK](https://stackoverflow.com/questions/5228892/ignorecase-in-awk) – Wiktor Stribiżew Sep 27 '21 at 08:01
  • Try without the semicolons `;` `echo 'Create' | awk '{IGNORECASE = 1} /create/'` returns `Create` and `echo 'Create' | awk 'BEGIN{IGNORECASE = 1} /create/'` also returns `Create` – Carlos Pascual Sep 27 '21 at 09:00
  • @RavinderSingh13 this is mt version : mawk 1.3.3 Nov 1996, Copyright (C) Michael D. Brennan compiled limits: max NF 32767 sprintf buffer 2040 – Pro_gram_mer Sep 27 '21 at 09:54
  • @RenaudPacalet I am currently using ubuntu 18.04 . – Pro_gram_mer Sep 27 '21 at 09:55
  • 1
    @WiktorStribiżew No ,actually I visited this page before I asked this question , And I typed the command in the page you mentioned yields different result , that's the reason I called it "unexpected behavior" . – Pro_gram_mer Sep 27 '21 at 09:58
  • @CarlosPascual echo 'Create' | awk 'BEGIN{IGNORECASE = 1} /create/' This one returns nothing still . – Pro_gram_mer Sep 27 '21 at 09:59
  • No, it returns the expected result. See [this demo screen](https://imgur.com/a/UH7hjMw). See [this online demo](https://ideone.com/d3iMhr). – Wiktor Stribiżew Sep 27 '21 at 10:36
  • 1
    @Pro_gram_mer Are you really using a 25 years old version of awk? Is there any good reason for not installing the latest GNU awk version supported by your Ubuntu distribution? Anyway, `IGNORECASE` is a GNU awk extension, not available in your `mawk`. `IGNORECASE = 1; /create/;` only apparently works. In fact it does not work at all but `IGNORECASE = 1` is interpreted as a condition. And as it evaluates as true, the result is that all input lines are printed once. The `/create/` condition does not match, due to the letter case, and nothing is printed for it. – Renaud Pacalet Sep 27 '21 at 10:58
  • 1
    @Pro_gram_mer Try to replace `/create/` by `/Create/` and you'll see that `Create` is printed twice: one time for the `IGNORECASE = 1` always true condition and one more time for the matching `/Create/` condition. Then try to process anything else (`echo foobar | awk 'IGNORECASE = 1;/create/;'`) and see that `foobar` is still printed once for the `IGNORECASE = 1` always true condition. – Renaud Pacalet Sep 27 '21 at 11:07
  • 1
    Regarding `mawk 1.3.3 Nov 1996` - get a newer version of awk, preferably GNU awk 5.1.0, as there have been some improvements in the last quarter century! – Ed Morton Sep 27 '21 at 12:09

1 Answers1

3

IGNORECASEis a GNU extension and you are not using GNU awk so

  1. BEGIN{IGNORECASE=1} sets an unused variable, just like doing BEGIN{FOO=1} and so the /create/ after it still won't match Create.
  2. IGNORECASE=1; outside of any action block is setting a variable and then testing the result of setting that variable, which is now 1/true, and so invoking the default action given a true condition of printing the current line. The /create/ after it is still not matching Create.

Look:

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

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

$ echo foo | awk 'whatever=1'
foo

To do a case-insensitive match on a lower-case regexp as you're trying to do would be the following in any awk:

$ echo 'Create' | awk 'tolower($0) ~ /create/'
Create

Get the book Effective AWK Programming, 5th Edition, by Arnold Robbins and read the first few pages to understand AWK syntax.

Ed Morton
  • 188,023
  • 17
  • 78
  • 185