Calling an executable program using awk

I have a program in C that I want to call by using awk in shell scripting. How can I do something like this?


Solution 1:

From the AWK man page:

system(cmd)
              executes cmd and returns its exit status

The GNU AWK manual also has a section that, in part, describes the system function and provides an example:

system("date | mail -s 'awk run done' root")

Solution 2:

A much more robust way would be to use the getline() function of GNU awk to use a variable from a pipe. In form cmd | getline result, cmd is run, then its output is piped to getline. It returns 1 if got output, 0 if EOF, -1 on failure.

First construct the command to run in a variable in the BEGIN clause if the command is not dependant on the contents of the file, e.g. a simple date or an ls.

A simple example of the above would be

awk 'BEGIN {
    cmd = "ls -lrth"
    while ( ( cmd | getline result ) > 0 ) {
        print result
    }
    close(cmd);
}'

When the command to run is part of the columnar content of a file, you generate the cmd string in the main {..} as below. E.g. consider a file whose $2 contains the name of the file and you want it to be replaced with the md5sum hash content of the file. You can do

awk '{ cmd = "md5sum "$2
       while ( ( cmd | getline md5result ) > 0 ) { 
           $2 = md5result
       }
       close(cmd);
 }1'

Another frequent usage involving external commands in awk is during date processing when your awk does not support time functions out of the box with mktime(), strftime() functions.

Consider a case when you have Unix EPOCH timestamp stored in a column and you want to convert that to a human readable date format. Assuming GNU date is available

awk '{ cmd = "date -d @" $1 " +\"%d-%m-%Y %H:%M:%S\"" 
       while ( ( cmd | getline fmtDate) > 0 ) { 
           $1 = fmtDate
       }
       close(cmd);
}1' 

for an input string as

1572608319 foo bar zoo

the above command produces an output as

01-11-2019 07:38:39 foo bar zoo

The command can be tailored to modify the date fields on any of the columns in a given line. Note that -d is a GNU specific extension, the *BSD variants support -f ( though not exactly similar to -d).

More information about getline can be referred to from this AllAboutGetline article at awk.freeshell.org page.

Solution 3:

There are several ways.

  1. awk has a system() function that will run a shell command:

    system("cmd")

  2. You can print to a pipe:

    print "blah" | "cmd"

  3. You can have awk construct commands, and pipe all the output to the shell:

    awk 'some script' | sh