Passing arguments to awk script
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).
Related videos on Youtube
Ada
Updated on September 18, 2022Comments
-
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 hitsawk: ./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 almost 6 yearsWhile the other Answers were good this was able to solve my problem in the most straight forward manner. Cheers
-
ilkkachu almost 6 yearsmaybe something like
BEGIN{for(i in ARGV) ZARGV[i]=ARGV[i]; delete ARGV}
to handle an arbitrary number of arguments?