Cómo detectar mediante programación el sabor awk (por ejemplo, gawk vs nawk)


8

Estoy usando una aplicación de línea de comandos que es esencialmente una colección de scripts de shell bash. La aplicación fue escrita para ejecutarse en BSD / OSX y también en Linux. Uno de los guiones se basa en awk. Contiene dos comandos awk: uno escrito para nawk (la implementación estándar BSD awk) y uno escrito para gawk (la implementación GNU awk).

Los dos comandos awk en cuestión no son compatibles con los diferentes entornos; en particular, el comando nawk falla cuando se ejecuta con gawk. El script verifica el nombre del kernel (es decir uname -s) para determinar el entorno del host y luego ejecuta el comando awk apropiado. Sin embargo, prefiero trabajar en Mac OS X con las utilidades principales de GNU instaladas, por lo que el script no se ejecuta correctamente.

En el proceso de pensar en la mejor manera de corregir este error, se me ocurrió que sería bueno saber cómo distinguir mediante programación entre diferentes tipos de utilidades comunes de línea de comandos, preferiblemente de una manera relativamente robusta y portátil.

Noté que nawk no acepta la bandera '-V' para imprimir la información de la versión, así que pensé que algo como lo siguiente debería funcionar:

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

Otra variación podría ser:

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

Esto parece funcionar en mis dos entornos de prueba (OS X y CentOS). Aquí están mis preguntas:

  • ¿Es este el mejor camino a seguir?
  • ¿Hay alguna manera de extender esto para manejar otras variaciones de awk (por ejemplo, mawk, jawk, etc.)?
  • ¿Vale la pena preocuparse por otras versiones de awk?

También debo mencionar que sé muy poco sobre awk.


Si el comando awk no es extremadamente complicado, o incluso si lo es, puede considerar portarlo a Perl u otra cosa que sea uniforme.
Comodín el

Veamos la versión awk en awk -Wvlugar del entorno host
Costas

1
Mi awk es muy débil pero creo que es bastante simple. De hecho, ya lo reescribí en puro bash. Pero esta es una de esas situaciones en las que estoy más interesado en satisfacer mi curiosidad que en resolver el problema original.
igal

@Costas Algo así se me ocurrió, pero no estaba seguro de lo frágil que podría ser; Sé muy poco sobre awk. He agregado mi solución actual a mi publicación.
igal

1
Una alternativa es ignorar qué versión de awkse está utilizando y codificar en su lugar la especificación POSIX .
chepner

Respuestas:


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

Alternativamente, test is awk es un enlace simbólico:

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

Este está bien ... pero hay algunas variaciones (difíciles de distinguir) para las versiones antiguas de awk, nawk y BWK más nuevas. Para aquellos, un script de muestra puede ser adaptado.
Thomas Dickey

3

Intente usar el whichcomando y use su código de salida.

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

luego formatee su script para usar la variable como comando

$command '{print $1}` 

se leería como

nawk '{print $1}`

si whichencuentra nawk. De lo contrario, usaríagawk


1
dado que commandes un bash incorporado, es posible que desee usar un nombre diferente para su variable, y también puede que desee ver la respuesta increíblemente detallada sobre por qué para muchos shells hay mejores alternativas a whichen unix.stackexchange.com/a/85250/109842
Eric Renouf

1

GNU Awk a menudo se instala como gawk, con awkun enlace simbólico en sistemas en los que GNU es el valor predeterminado. Supongo que este es el caso en los sistemas BSD y OS X, ya que ya tienen los suyos awk.

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

Gracias por su aporte. Esta es una buena idea y tiene razón en que este es el caso para mí en OS X. Pero esperaba una solución intrínseca, por así decirlo.
igal

0

Un truco sucio

if nawk 'BEGIN { nawk-only-function() ;}' 
then 
   nawk -f nfile.awk ...
else 
   gawk -f gfile.awk ...
fi
  • donde nawk-only-function() existe solo ennawk

-2

Probablemente intente abusar de la macro AC_PROG_AWK m4 en autoconf para elegir una, ordenándolas adecuadamente. Aunque probablemente sea exagerado


¿Podría editar para proporcionar un poco más de detalle sobre cómo usaría esa macro para este escenario?
Michael Homer

En realidad no dice cuál encontró, sino que simplemente busca implementaciones awk y elige una en función de su nombre.
Thomas Dickey
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.