Passing arguments to awk script

7,310

Solution 1

The moment awk hits the main body of the script, after BEGIN, it's going to want to read the filenames specified in ARGV[x]. So just nuke 'em.

$ cat a.awk
#!/bin/awk -f
BEGIN {
print "AWK Script Starting"
ZARGV[1]=ARGV[1]
ZARGV[2]=ARGV[2]
ARGV[1]=""
ARGV[2]=""
}
{
    if ($0 < ZARGV[1])
        print $0
    else if ($0 < ZARGV[2])
        print $0 + ZARGV[2]
}
$

Example:

$ cat logfile
1
2
3
4
5
$ ./a.awk 3 4 <logfile
AWK Script Starting
1
2
7
$

Solution 2

Just for the fun of it (and this is certainly NOT the recommended way to do it): As awk doesn't know about "positional parameters" (PP) but only variable assignments and input filenames, we need to dissect the PP out and tell them from the other two. This could be done by either separating the PP with a fixed token, e.g. -- (which is used in other context as well), or by knowing the PP count, either fixed or conveyed in e.g. ARGV[1]). Try

    awk '
    BEGIN   {while (ARGV[++MXPP] != "--")   PP[MXPP]     = ARGV[MXPP]
             for (j=MXPP+1; j<ARGC; j++)    ARGV[j-MXPP] = ARGV[j]
             ARGC -= --MXPP
            }

            {if ($0 < ARGV[1])
             print $0
             else if ($0 < ARGV[2])
             print $0 + ARGV[2]             
            }
    ' VAR1 VAR2 -- file[12]

If you use stdin in lieu of input files by piping sth in, you could omit the token and fetch the PP until the end of the list (i.e. set token to "")

Solution 3

You already know about -v variable=value. The other way is to pass variables through the environment and read them from the ENVIRON array:

$ var1=hello var2=world awk 'BEGIN { print ENVIRON["var1"], ENVIRON["var2"] }'
hello world

This sets the environment variables var1 and var2 in awk's environment only.

Or,

$ export var1=hello var2=world
$ awk 'BEGIN { print ENVIRON["var1"], ENVIRON["var2"] }'
hello world

This sets the variables in the calling environment before calling awk.

The ARGV array contains only the filenames that the awk program will read from in sequence, but it may also contain variable names set on the command line, as in

awk '...' var1=value1 var2=value2 filename

This is generally not a recommended way of passing variables into awk though (these variables would not be available in a BEGIN block for instance).

Share:
7,310

Related videos on Youtube

Ada
Author by

Ada

Updated on September 18, 2022

Comments

  • Ada
    Ada almost 2 years

    I have a awk script where i want to be able to pass N arguments into it and also read from stdin. I would like to be able to do something like

    tail -f logfile | my_cool_awk_scipt var1 var2 var3 ... varN

    And then use these variables inside the script.

    #!/bin/awk -f
    
    BEGIN { 
    print "AWK Script Starting" 
    print ARGV[1]
    }                                                                              
    {
        if ($0 < ARGV[1])
            print $0
        else if ($0 < ARGV[2])
            print $0 + ARGV[2]             
    }
      
    

    If i try to pass the variables as it stands it print ARGV[1] and then hits

    awk: ./my_cool_awk_script:4: fatal: cannot open file `var1' for reading (No such file or directory)
    

    I can do,

    tail -f logfile | my_cool_awk_scipt -v var1=var1 -v var2=var2 -v var3=var3 ... varN=varN
    

    but this is a bit limiting and verbose. I know I can also wrap this in a shell script but am unsure a clean way to embed what I have into something like that.

  • Ada
    Ada almost 6 years
    While the other Answers were good this was able to solve my problem in the most straight forward manner. Cheers
  • ilkkachu
    ilkkachu almost 6 years
    maybe something like BEGIN{for(i in ARGV) ZARGV[i]=ARGV[i]; delete ARGV} to handle an arbitrary number of arguments?