Como detectar programaticamente o sabor do awk (por exemplo, gawk vs nawk)

8

Estou usando um aplicativo de linha de comando que é essencialmente uma coleção de scripts de shell bash. O aplicativo foi escrito para rodar no BSD / OSX e também no Linux. Um dos scripts depende do awk. Ele contém dois comandos awk: um escrito para o nawk (a implementação padrão do awd do BSD) e um escrito para o gawk (a implementação do GNU awk).

Os dois comandos awk em questão não são compatíveis com os diferentes ambientes; em particular, o comando nawk falha quando executado com o gawk. O script verifica o nome do kernel (por exemplo, uname -s ) para determinar o ambiente do host e, em seguida, executa o comando awk apropriado. No entanto, prefiro trabalhar com o Mac OS X com os utilitários principais GNU instalados, portanto, o script não é executado corretamente.

No processo de pensar sobre a melhor forma de corrigir esse bug, ocorreu-me que seria interessante saber como distinguir programaticamente diferentes tipos de utilitários de linha de comando comuns, de preferência de maneira relativamente robusta e portátil.

Percebi que o nawk não aceita o sinalizador '-V' para imprimir as informações da versão, então imaginei que algo como o seguinte deveria funcionar:

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

Outra variação poderia ser:

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

Isso parece funcionar em meus dois ambientes de teste (OS X e CentOS). Aqui estão minhas perguntas:

  • Este é o melhor caminho a seguir?
  • Existe uma maneira de estender isso para lidar com outras variações do awk (por exemplo, mawk, jawk, etc.)?
  • Vale a pena se preocupar com outras versões do awk?

Eu também devo mencionar que eu sei muito pouco sobre o awk.

    
por igal 16.10.2015 / 15:22

5 respostas

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, teste é awk é um link simbólico:

awk=$( command -v awk )
[[ -L $awk ]] && readlink $awk # make some decision about the result of that
    
por 16.10.2015 / 16:07
3

Tente usar o comando which e use seu código de saída.

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

formate seu script para usar a variável como o comando

$command '{print $1}' 

seria lido como

nawk '{print $1}'

se which encontrar nawk. Caso contrário, usaria gawk

    
por 16.10.2015 / 16:11
1

O GNU Awk é frequentemente instalado como gawk , com awk como um link simbólico para ele em sistemas onde o GNU é o padrão. Eu acho que esse é o caso dos sistemas BSD e OS X, já que eles já possuem seus próprios awk .

if gawk '{ exit; }' < /dev/null 2> /dev/null
then
    echo "gawk available"
else
    echo "gawk not available"
fi
    
por 16.10.2015 / 15:57
0

Um hack sujo

if nawk 'BEGIN { nawk-only-function() ;}' 
then 
   nawk -f nfile.awk ...
else 
   gawk -f gfile.awk ...
fi
  • onde nawk-only-function() existe apenas em nawk
por 16.10.2015 / 15:36
-2

Eu provavelmente tentaria abusar da macro m4 AC_PROG_AWK no autoconf para escolher uma, ordenando-as adequadamente. Provavelmente é um exagero embora

    
por 17.10.2015 / 01:25