Passing arguments to awk script
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
2
down vote
favorite
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.
Thanks in advanced.
shell-script shell awk gawk
add a comment |Â
up vote
2
down vote
favorite
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.
Thanks in advanced.
shell-script shell awk gawk
add a comment |Â
up vote
2
down vote
favorite
up vote
2
down vote
favorite
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.
Thanks in advanced.
shell-script shell awk gawk
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.
Thanks in advanced.
shell-script shell awk gawk
edited Aug 3 at 15:52
ilkkachu
47.3k668130
47.3k668130
asked Aug 3 at 15:50
AdamR
134
134
add a comment |Â
add a comment |Â
4 Answers
4
active
oldest
votes
up vote
0
down vote
accepted
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
$
1
While the other Answers were good this was able to solve my problem in the most straight forward manner. Cheers
â AdamR
Aug 3 at 16:30
1
maybe something likeBEGINfor(i in ARGV) ZARGV[i]=ARGV[i]; delete ARGV
to handle an arbitrary number of arguments?
â ilkkachu
Aug 3 at 16:52
add a comment |Â
up vote
0
down vote
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).
add a comment |Â
up vote
0
down vote
You could build a script like this:
#!/bin/bash
vars=()
i=1
for arg in "$@"; do
vars+=(-v "var$i=$arg")
i=$((i+1))
done
awk "$vars[@]" -f/dev/fd/3 3<< EOF
BEGIN
printf "awk var1: %sn", var1;
printf "awk var2: %sn", var2;
1
EOF
and then run it:
$ echo some input | ./awk.sh foo bar doo
awk var1: foo
awk var2: bar
some input
The shell script will build a command line of those -v var1=...
arguments, and pass those to awk
, with the the actual awk program through a here-doc (of course you could have the awk script in a separate file instead). You can't pass any names of the input files this way, though, you're forced to have the awk script read from stdin.
At least GNU awk explicitly documents that ARGV[n]
are used as the input files too (https://www.gnu.org/software/gawk/manual/html_node/ARGC-and-ARGV.html), which is why you get the "file not found" errors.
add a comment |Â
up vote
0
down vote
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 "")
add a comment |Â
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
0
down vote
accepted
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
$
1
While the other Answers were good this was able to solve my problem in the most straight forward manner. Cheers
â AdamR
Aug 3 at 16:30
1
maybe something likeBEGINfor(i in ARGV) ZARGV[i]=ARGV[i]; delete ARGV
to handle an arbitrary number of arguments?
â ilkkachu
Aug 3 at 16:52
add a comment |Â
up vote
0
down vote
accepted
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
$
1
While the other Answers were good this was able to solve my problem in the most straight forward manner. Cheers
â AdamR
Aug 3 at 16:30
1
maybe something likeBEGINfor(i in ARGV) ZARGV[i]=ARGV[i]; delete ARGV
to handle an arbitrary number of arguments?
â ilkkachu
Aug 3 at 16:52
add a comment |Â
up vote
0
down vote
accepted
up vote
0
down vote
accepted
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
$
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
$
answered Aug 3 at 16:12
steve
11.9k22047
11.9k22047
1
While the other Answers were good this was able to solve my problem in the most straight forward manner. Cheers
â AdamR
Aug 3 at 16:30
1
maybe something likeBEGINfor(i in ARGV) ZARGV[i]=ARGV[i]; delete ARGV
to handle an arbitrary number of arguments?
â ilkkachu
Aug 3 at 16:52
add a comment |Â
1
While the other Answers were good this was able to solve my problem in the most straight forward manner. Cheers
â AdamR
Aug 3 at 16:30
1
maybe something likeBEGINfor(i in ARGV) ZARGV[i]=ARGV[i]; delete ARGV
to handle an arbitrary number of arguments?
â ilkkachu
Aug 3 at 16:52
1
1
While the other Answers were good this was able to solve my problem in the most straight forward manner. Cheers
â AdamR
Aug 3 at 16:30
While the other Answers were good this was able to solve my problem in the most straight forward manner. Cheers
â AdamR
Aug 3 at 16:30
1
1
maybe something like
BEGINfor(i in ARGV) ZARGV[i]=ARGV[i]; delete ARGV
to handle an arbitrary number of arguments?â ilkkachu
Aug 3 at 16:52
maybe something like
BEGINfor(i in ARGV) ZARGV[i]=ARGV[i]; delete ARGV
to handle an arbitrary number of arguments?â ilkkachu
Aug 3 at 16:52
add a comment |Â
up vote
0
down vote
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).
add a comment |Â
up vote
0
down vote
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).
add a comment |Â
up vote
0
down vote
up vote
0
down vote
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).
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).
edited Aug 3 at 16:02
answered Aug 3 at 15:57
Kusalananda
100k13199311
100k13199311
add a comment |Â
add a comment |Â
up vote
0
down vote
You could build a script like this:
#!/bin/bash
vars=()
i=1
for arg in "$@"; do
vars+=(-v "var$i=$arg")
i=$((i+1))
done
awk "$vars[@]" -f/dev/fd/3 3<< EOF
BEGIN
printf "awk var1: %sn", var1;
printf "awk var2: %sn", var2;
1
EOF
and then run it:
$ echo some input | ./awk.sh foo bar doo
awk var1: foo
awk var2: bar
some input
The shell script will build a command line of those -v var1=...
arguments, and pass those to awk
, with the the actual awk program through a here-doc (of course you could have the awk script in a separate file instead). You can't pass any names of the input files this way, though, you're forced to have the awk script read from stdin.
At least GNU awk explicitly documents that ARGV[n]
are used as the input files too (https://www.gnu.org/software/gawk/manual/html_node/ARGC-and-ARGV.html), which is why you get the "file not found" errors.
add a comment |Â
up vote
0
down vote
You could build a script like this:
#!/bin/bash
vars=()
i=1
for arg in "$@"; do
vars+=(-v "var$i=$arg")
i=$((i+1))
done
awk "$vars[@]" -f/dev/fd/3 3<< EOF
BEGIN
printf "awk var1: %sn", var1;
printf "awk var2: %sn", var2;
1
EOF
and then run it:
$ echo some input | ./awk.sh foo bar doo
awk var1: foo
awk var2: bar
some input
The shell script will build a command line of those -v var1=...
arguments, and pass those to awk
, with the the actual awk program through a here-doc (of course you could have the awk script in a separate file instead). You can't pass any names of the input files this way, though, you're forced to have the awk script read from stdin.
At least GNU awk explicitly documents that ARGV[n]
are used as the input files too (https://www.gnu.org/software/gawk/manual/html_node/ARGC-and-ARGV.html), which is why you get the "file not found" errors.
add a comment |Â
up vote
0
down vote
up vote
0
down vote
You could build a script like this:
#!/bin/bash
vars=()
i=1
for arg in "$@"; do
vars+=(-v "var$i=$arg")
i=$((i+1))
done
awk "$vars[@]" -f/dev/fd/3 3<< EOF
BEGIN
printf "awk var1: %sn", var1;
printf "awk var2: %sn", var2;
1
EOF
and then run it:
$ echo some input | ./awk.sh foo bar doo
awk var1: foo
awk var2: bar
some input
The shell script will build a command line of those -v var1=...
arguments, and pass those to awk
, with the the actual awk program through a here-doc (of course you could have the awk script in a separate file instead). You can't pass any names of the input files this way, though, you're forced to have the awk script read from stdin.
At least GNU awk explicitly documents that ARGV[n]
are used as the input files too (https://www.gnu.org/software/gawk/manual/html_node/ARGC-and-ARGV.html), which is why you get the "file not found" errors.
You could build a script like this:
#!/bin/bash
vars=()
i=1
for arg in "$@"; do
vars+=(-v "var$i=$arg")
i=$((i+1))
done
awk "$vars[@]" -f/dev/fd/3 3<< EOF
BEGIN
printf "awk var1: %sn", var1;
printf "awk var2: %sn", var2;
1
EOF
and then run it:
$ echo some input | ./awk.sh foo bar doo
awk var1: foo
awk var2: bar
some input
The shell script will build a command line of those -v var1=...
arguments, and pass those to awk
, with the the actual awk program through a here-doc (of course you could have the awk script in a separate file instead). You can't pass any names of the input files this way, though, you're forced to have the awk script read from stdin.
At least GNU awk explicitly documents that ARGV[n]
are used as the input files too (https://www.gnu.org/software/gawk/manual/html_node/ARGC-and-ARGV.html), which is why you get the "file not found" errors.
answered Aug 3 at 16:06
ilkkachu
47.3k668130
47.3k668130
add a comment |Â
add a comment |Â
up vote
0
down vote
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 "")
add a comment |Â
up vote
0
down vote
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 "")
add a comment |Â
up vote
0
down vote
up vote
0
down vote
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 "")
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 "")
answered Aug 3 at 17:21
RudiC
762
762
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f460366%2fpassing-arguments-to-awk-script%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password