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 ser executado no BSD / OSX e também no Linux. Um dos scripts depende do awk. Ele contém dois comandos awk: um escrito para nawk (a implementação padrão do BSD awk) e outro escrito para gawk (a implementação GNU awk).

Os dois comandos do 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 (ou seja uname -s) para determinar o ambiente host e, em seguida, executa o comando awk apropriado. No entanto, prefiro trabalhar no Mac OS X com os principais utilitários do GNU instalados, para que o script não seja executado corretamente.

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

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

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

Outra variação pode ser:

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

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

  • Este é o melhor caminho a percorrer?
  • 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?

Também devo mencionar que sei muito pouco sobre o awk.


Se o comando awk não for extremamente complicado, ou mesmo se for, considere portá-lo para perl ou qualquer outra coisa que seja uniforme.
— Wildcard

Vamos ver a versão awk por awk -Wvem vez de ambiente de acolhimento
— Costas

1
Meu awk é muito fraco, mas acredito que seja bastante simples. Na verdade, eu já o reescrevi em pura festa. Mas essa é uma daquelas situações em que estou mais interessado em satisfazer minha curiosidade do que em resolver o problema original.
— igal #

@Costas Algo assim realmente me ocorreu, mas eu não tinha certeza de quão frágil poderia ser; Eu sei muito pouco sobre awk. Adicionei minha solução atual à minha postagem.
— igal #

1
Uma alternativa é ignorar qual versão awkestá sendo usada e, em vez disso, codificar para a especificação POSIX .
— Chepner # 16/15

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

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

Este é bom ... mas há algumas variações (difíceis de distinguir) para as versões old-awk, nawk e as mais recentes do BWK. Para esses, um exemplo de script pode ser adaptado.
— 21815 Thomas

3

Tente usar o whichcomando 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 whichencontra nawk. Caso contrário, ele usariagawk


1
desde que commandé uma festança embutido que você pode querer usar um nome diferente para a variável, e você também pode querer ver a resposta incrivelmente detalhado sobre o porquê de muitas conchas há melhores alternativas para whicha unix.stackexchange.com/a/85250/109842
— Eric Renouf

1

GNU Awk é muitas vezes instalado como gawk, com awkum link simbólico para ele em sistemas onde GNU é o padrão. Eu acho que esse é o caso dos sistemas BSD e OS X, já que eles já têm os seus awk.

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

Obrigdo por sua contribuição. Essa é uma boa ideia e você está certo de que esse é o meu caso no OS X. Mas eu esperava uma solução intrínseca, por assim dizer.
— igal #

0

Um truque sujo

if nawk 'BEGIN { nawk-only-function() ;}' 
then 
   nawk -f nfile.awk ...
else 
   gawk -f gfile.awk ...
fi
  • onde nawk-only-function() existe apenas emnawk

-2

Provavelmente tentaria abusar da macro AC_PROG_AWK m4 no autoconf para escolher uma, ordenando-as de maneira apropriada. Provavelmente é um exagero


Você poderia editar para fornecer um pouco mais de detalhes sobre como você usaria essa macro para esse cenário?
— Michael Homer

Na verdade, ele não diz qual foi encontrado, mas simplesmente procura implementações do awk e escolhe uma com base em seu nome.
— Thomas Dickey
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.