11

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.

igal
  • 9,666
  • 1
  • 42
  • 58
  • 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](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/awk.html) instead. – chepner Oct 16 '15 at 18:23
  • I too know little about `awk` and I have a book on it! I have hit several times the case where my "slick" awk code didn't work when I moved it from Solaris to Linux, or to HP-UX. The book starts out by saying "There are a lot of awk versions ..." so the hack answer or the perl answer might be appropriate if you know your script will be running in under various Unix flavors. – Mark Stewart Oct 16 '15 at 18:40
  • The usual way to do this is to test the operating system using 'uname', and then to choose the expected command based on the OS. – Douglas Held Oct 17 '15 at 04:29
  • @DouglasHeld As I mentioned in the original post, checking the OS (with uname) is the method that is currently failing due to having GNU utilities installed on a BSD system. – igal Oct 17 '15 at 16:10
  • You've not selected an answer here. Does that mean that none of these solutions worked?...or something else? – Seamus Feb 15 '22 at 05:53
  • None of these are a complete solution, in my opinion. It seems that there may not be a good solution. – igal Feb 15 '22 at 08:58

6 Answers6

11
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
glenn jackman
  • 84,176
  • 15
  • 116
  • 168
  • 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

Kip K
  • 123
  • 4
  • 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 http://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
James Sneeringer
  • 2,512
  • 13
  • 14
  • 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
  • This is very innacurate, as there are many more versions of awk than just "mawk / gawk" (regular awk, for exemple, is neither) – Olivier Dulac Sep 21 '20 at 17:22
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
Archemar
  • 31,183
  • 18
  • 69
  • 104
  • This would be really useful with an example of what `nawk-only-function` might be. But as presented this anwer is not helpful. – symcbean May 16 '23 at 16:12
0

You can run awk -W version.

Here is some example output:

enter image description here

Please let me know if this works or not!

  • Welcome to the site, and thank you for your contribution. Please note that this seems to be no different from the [answer by glenn jackman](https://unix.stackexchange.com/a/236666/377345). If that was not intended, please consider revising your post to make the difference in the approach more prominent. – AdminBee Jun 12 '23 at 16:01
-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

ssta
  • 99
  • 1