8

I'm using a command-line application which is essentially a collection of bash shell scripts. The application was written to run on BSD/OSX and also on Linux. One of the scripts relies on awk. It contains two awk commands: one written for nawk (the standard BSD awk implementation) and one written for gawk (the GNU awk implementation).

The two awk commands in question are not cross-compatible with the different environments; in particular the nawk command fails when run with gawk. The script checks the kernel name (i.e. uname -s) in order to determine the host environment, and then runs the appropriate awk command. However I prefer to work on Mac OS X with the GNU core utilities installed, so the script fails to run correctly.

In the process of thinking about how best to fix this bug it occurred to me that it would be nice to know how to programmatically distinguish between different flavors of the common command-line utilities, preferably in a relatively robust and portable way.

I noticed that nawk doesn't accept the '-V' flag to print the version information, so I figured that something like the following should work:

awk -V &>/dev/null && echo gawk || echo nawk

Another variation could be:

awk -Wversion &>/dev/null && echo gawk || echo nawk

This seems to work on my two testing environments (OS X and CentOS). Here are my questions:

  • Is this the best way to go?
  • Is there a way to extend this to handle other variations of awk (e.g. mawk, jawk, etc.)?
  • Is it even worth worrying about other versions of awk?

I should also mention that I know very little about awk.

  • If the awk command isn't extremely complicated, or even if it is, you might consider porting it to perl or something else which is uniform. – Wildcard Oct 16 '15 at 13:30
  • Let see awk version by awk -Wv instead of host environment – Costas Oct 16 '15 at 13:35
  • 1
    My awk is very weak but I believe that it is quite simple. I actually already rewrote it in pure bash. But this is one of those situations where I'm more interested in satisfying my curiosity than in actually solving the original problem. – igal Oct 16 '15 at 13:37
  • @Costas Something like that actually did occur to me, but I wasn't sure how fragile it might be; I know very little about awk. I've added my current solution to my post. – igal Oct 16 '15 at 13:49
  • 1
    One alternative is to ignore what version of awk is being used, and code to the POSIX specification instead. – chepner Oct 16 '15 at 18:23
7
if awk --version 2>&1 | grep -q "GNU Awk"
then
    awk 'BEGIN {print "I am GNU Awk"}'

elif awk -Wv 2>&1 | grep -q "mawk"
then
    awk 'BEGIN {print "I am mawk"}'

else
    awk 'BEGIN {print "I might be nawk, might not be"}'
fi

Alternatively, test is awk is a symbolic link:

awk=$( command -v awk )
[[ -L $awk ]] && readlink $awk # make some decision about the result of that
  • This one is okay... but there are a few variations (hard to distinguish) for old-awk, nawk, and the newer BWK versions. For those, a sample script might be be tailored. – Thomas Dickey Oct 18 '15 at 17:45
3

Try using the which command and use its exit code.

which nawk
if [[ $? == 0 ]]; then
    command="nawk"
else
    command="gawk"
fi

then format your script to use the variable as the command

$command '{print $1}` 

would be read as

nawk '{print $1}`

if which finds nawk. Otherwise it would use gawk

  • 1
    since command is a bash builtin you might want to use a different name for your variable, and you might also want to see the incredibly detailed answer about why for many shells there are better alternatives to which at unix.stackexchange.com/a/85250/109842 – Eric Renouf Oct 16 '15 at 14:33
1

GNU Awk is often installed as gawk, with awk as a symlink to it on systems where GNU is the default. I would guess this is the case on BSD and OS X systems, since they already have their own awk.

if gawk '{ exit; }' < /dev/null 2> /dev/null
then
    echo "gawk available"
else
    echo "gawk not available"
fi
  • Thank you for your input. This is a good idea and you're correct that this is the case for me on OS X. But I was hoping for an intrinsic solution, so to speak. – igal Oct 16 '15 at 14:16
0

A dirty hack

if nawk 'BEGIN { nawk-only-function() ;}' 
then 
   nawk -f nfile.awk ...
else 
   gawk -f gfile.awk ...
fi
  • where nawk-only-function() exist only on nawk
-2

I'd probably try abusing the AC_PROG_AWK m4 macro in autoconf to choose one, ordering them appropriately. It's probably overkill though

  • Could you edit to provide a bit more detail on how you'd use that macro for this scenario? – Michael Homer Oct 17 '15 at 0:33
  • It doesn't actually tell which one it found, but simply looks for awk implementations and chooses one based on its name. – Thomas Dickey Oct 18 '15 at 17:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.