System calls, AWK, and Bringing in external inputs
awk
can access environment variables using the ENVIRON
special array. However, while you can assign values to elements of that array, it is not passed in the environment of the commands executed by awk
's system
, | getline
or print |
. That ENVIRON
array is only intended for awk
to get the value of the environment variables it is passed.
You can do: system("ls " var)
, but beware that the string that is passed to awk
's system()
(or print |
or | getline
) is actually passed as an argument to sh -c
, so it is interpreted as shell code.
For instance, if the awk
var
variable contains foo;rm -rf /
, it will not tell ls
to list the file called "foo;rm -rf /"
but instead to list the file called foo
and then the rm
command will be run.
So, you may need to escape all the characters special to the shell in that var
variable.
This could be done for instance with:
awk '
function escape(s) {
gsub(/'\''/, "&\\\\&&", s)
return "'\''" s "'\''"
}
{
cmd = "date -d " escape($0) " +%s"
cmd | getline seconds
close(cmd)
print seconds
}'
While that means running one shell and one date
command per line, you might as well do the reading of the file with the shell itself:
while IFS= read <&3 -r line; do
date -d "$line" +%s
done 3< the-file
Related videos on Youtube
Comments
-
David Kegyes almost 2 years
awk '{ TEMPVAR="/usr/bin"; printf("%s", system("ls $TEMPVAR")); }' empty
In this example I'm trying to bring in the variable
TEMPVAR
into thesystem
call. How would I do this?What I'm aiming to do: I'm trying to use
date -d $0 +%s
in asystem
call that occurs every line of a file. However, I'm struggling with how to get that$0
value into the system call. -
Lekensteyn over 10 yearsFor future readers that wonder why so many quotes and backslashes are used, this is because the snippet is a **shell command too. What you basically need to do is to put single quotes around the argument and substitute the single quotes in the argument by
'\''
(end string, insert\'
, continue string). In an AWK script (file), it is sufficient to usegsub(/'/, "'\\''", s); return "'" s "'";
, but for a "one-liner" command, the single quotes and backslashes must be escaped again as shown by Stephane.