Comment détecter par programmation la saveur awk (par exemple, gawk vs nawk)


8

J'utilise une application en ligne de commande qui est essentiellement une collection de scripts shell bash. L'application a été écrite pour fonctionner sur BSD / OSX et également sur Linux. L'un des scripts repose sur awk. Il contient deux commandes awk: une écrite pour nawk (l'implémentation standard BSD awk) et une écrite pour gawk (l'implémentation GNU awk).

Les deux commandes awk en question ne sont pas compatibles avec les différents environnements; en particulier, la commande nawk échoue lorsqu'elle est exécutée avec gawk. Le script vérifie le nom du noyau (c'est-à-dire uname -s) afin de déterminer l'environnement hôte, puis exécute la commande awk appropriée. Cependant, je préfère travailler sur Mac OS X avec les utilitaires GNU core installés, donc le script ne fonctionne pas correctement.

Dans le processus de réflexion sur la meilleure façon de corriger ce bogue, il m'est venu à l'esprit qu'il serait bien de savoir comment distinguer par programmation les différentes versions des utilitaires de ligne de commande courants, de préférence d'une manière relativement robuste et portable.

J'ai remarqué que nawk n'accepte pas l'indicateur '-V' pour imprimer les informations de version, j'ai donc pensé que quelque chose comme ce qui suit devrait fonctionner:

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

Une autre variante pourrait être:

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

Cela semble fonctionner sur mes deux environnements de test (OS X et CentOS). Voici mes questions:

  • Est-ce la meilleure façon de procéder?
  • Existe-t-il un moyen de l'étendre pour gérer d'autres variations de awk (par exemple mawk, jawk, etc.)?
  • Cela vaut-il même la peine de s'inquiéter pour les autres versions d'awk?

Je devrais également mentionner que je sais très peu de choses sur awk.


Si la commande awk n'est pas extrêmement compliquée, ou même si elle l'est, vous pouvez envisager de la porter sur perl ou autre chose qui est uniforme.
Wildcard du

Laissez voir la version awk par awk -Wvau lieu de l'environnement hôte
Costas

1
Mon awk est très faible mais je pense que c'est assez simple. En fait, je l'ai déjà réécrit en bash pur. Mais c'est une de ces situations où je suis plus intéressé à satisfaire ma curiosité qu'à résoudre réellement le problème d'origine.
igal

@Costas Quelque chose comme ça m'est venu à l'esprit, mais je n'étais pas sûr de sa fragilité; Je sais très peu de choses sur awk. J'ai ajouté ma solution actuelle à mon message.
igal

1
Une alternative est d'ignorer quelle version de awkest utilisée et de coder à la place la spécification POSIX .
chepner

Réponses:


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

Alternativement, test is awk est un lien symbolique:

awk=$( command -v awk )
[[ -L $awk ]] && readlink $awk # make some decision about the result of that

Celui-ci est correct ... mais il existe quelques variantes (difficiles à distinguer) pour les anciennes versions awk, nawk et les plus récentes BWK. Pour ceux-ci, un exemple de script peut être personnalisé.
Thomas Dickey

3

Essayez d'utiliser la whichcommande et utilisez son code de sortie.

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

puis formatez votre script pour utiliser la variable comme commande

$command '{print $1}` 

serait lu comme

nawk '{print $1}`

si whichtrouve nawk. Sinon, il utiliseraitgawk


1
comme commandc'est un bash intégré, vous voudrez peut-être utiliser un nom différent pour votre variable, et vous voudrez peut-être aussi voir la réponse incroyablement détaillée sur les raisons pour lesquelles pour de nombreux shells il existe de meilleures alternatives whichà unix.stackexchange.com/a/85250/109842
Eric Renouf

1

GNU Awk est souvent installé en tant que gawk, avec awkun lien symbolique vers celui-ci sur les systèmes où GNU est la valeur par défaut. Je suppose que c'est le cas sur les systèmes BSD et OS X, car ils ont déjà le leur awk.

if gawk '{ exit; }' < /dev/null 2> /dev/null
then
    echo "gawk available"
else
    echo "gawk not available"
fi

Merci pour votre participation. C'est une bonne idée et vous avez raison, c'est le cas pour moi sous OS X. Mais j'espérais pour ainsi dire une solution intrinsèque.
igal

0

Un hack sale

if nawk 'BEGIN { nawk-only-function() ;}' 
then 
   nawk -f nfile.awk ...
else 
   gawk -f gfile.awk ...
fi
  • nawk-only-function() n'existent que surnawk

-2

J'essaierais probablement d'abuser de la macro AC_PROG_AWK m4 dans autoconf pour en choisir une, en les commandant de manière appropriée. Mais c'est probablement exagéré


Pourriez-vous modifier pour fournir un peu plus de détails sur la façon dont vous utiliseriez cette macro pour ce scénario?
Michael Homer

Il ne dit pas réellement lequel il a trouvé, mais recherche simplement les implémentations awk et en choisit une en fonction de son nom.
Thomas Dickey
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.