How to auto correct a failing command?

If a command is not found, e.g. nawk, this is how I fix the problem

[[ -x /usr/bin/gawk ]] && NAWK=/usr/bin/gawk  
[[ -x /usr/bin/nawk ]] && NAWK=/usr/bin/nawk  
[[ -x /usr/bin/awk ]] && NAWK=/usr/bin/awk

I use $NAWK an the set the appropriate value based on the system it runs.

How can I implement a similar fix for a command found but illegal argument. See pseudo example below.

grep -o hello *
grep: invalid option -- o

If computer software could do that, it wouldn't really need you.

You need to rewrite that section without using nonportable options for it to be portable.

But sometimes one can do someting with nonportable options.
One example is the echo command. For ages I used echo \t\b\n to echo tab, bel or newline. But this does not work anymore in bash. If you want echo to interpret escaped characters, you must use the -e option: echo -e \t\b\n .
So portable scripts often use this construction:

if echo '\t' |grep t >/dev/null 
then   
  # -e option needed to interpret \t \n etc.
  ECHOOPTS=-e
else   
  # No options needed
  ECHOOPTS=""
fi
echo $ECHOOPTS "col1\tcol2\tcol3\n"

So this is what you can do: use variables to store options.

See, I don't think that actually helps you. There are systems where echo -e literally prints -e . Theoretically this script could detect and warn you when your code is broken, but it doesn't actually make your code portable. There's places -e is needed, places it's not, and places where echo never does what you want.

If you want your script to be portable, write it portably.

There is a command which handles escapes properly everywhere, in every shell: printf. Rewrite using printf instead of echo -e. Just a blind substitution won't work of course, you need to add an \n.

As an alternative for grep -o , awk.

1 Like

My requirement is less to play with the syntax of the command and moreso to use a different utility like ggrep or GNU grep for failing commands.

Can you suggest a good similar feasible solution ?

If you want code that will work on a variety of systems, the only way to do that portably is to write portable code to begin with.

You can't magically take a script that works on AIX systems using options that are only available on AIX and make it work on HP-UX, Solaris, and Linux systems. You can't magically take a script that works on HP-UX systems using options that are only available on HP-UX systems and make it work on AIX, Solaris, and Linux systems. You can't magically take a script that works on Solaris systems using options that are only available on Solaris systems and make it work on AIX, HP-UX, and Linux systems. You can't magically take a script that works on Debian Linux systems using options that are only available on Debian Linux systems and make it work on AIX, HP-UX, Solaris, and Red Hat Linux systems. ...

But, you can write a strictly conforming POSIX shell script and have it work perfectly on AIX, HP-UX, Solaris, and OS X systems (and if you're lucky, there is also a good chance that it will also work on many Linux systems and on many BSD systems).

He hasn't said so explicitly, but I've gained the impression that mohtashims has been required to maintain and port a lot of shell scripts not all his own devising, and hopes for cookie-cutter solutions for scripts written using non-portable options.

There a few strategies you can try.

  1. Substituting different commands on different systems.
  2. Building your own substitutes for every troublesome command.
  3. Re-factoring the scripts to use actually portable options.

Solution #1 obviously looks easier and more attractive, since hypothetically it can be done with just a "header" section and few to no changes to large amounts of code you may not necessarily understand. But if it really was better, you would have solved your problems months ago. You must be dealing with a large number of very different systems, as you're still finding and plugging hole after hole, and will continue to do so for a long time. What will you do when you hit one which doesn't have GNU extensions available?

Solution #2 is a big job. I've spent large amounts of time duplicating one command.

Solution #3 unfortunately means having to understand what grep -o actually means, so as to replace it. You may want to break it down and test commands individually rather than fighting it as one gigantic block of code.

My last comment: This is what happens when you try and detect and compensate for every difference between systems:

That's 800 kilobytes of ad-hoc corrections per decade, more or less.