Distribuindo um script: Devo usar / bin / gawk ou / usr / bin / gawk para shebang?

12

O gawk está em / bin ou / usr / bin normalmente? Eu aceitaria, #!/usr/bin/env gawkmas não posso usar argumentos. Agora eu estou usando #!/bin/gawk -f. O script é muito longo e contém muitas aspas simples e funciona com o stdin.

O manual GNU Awk possui a seção 1.1.4 Programas executáveis ​​do awk, onde ele usa #! / Bin / awk em seu exemplo, mas continua dizendo:

Observe que em muitos sistemas awkpode ser encontrado em /usr/binvez de em /bin. Advertência Emptor.

O que a maioria das pessoas faz? Eu li que o sed é supostamente padronizado em / bin, enquanto o perl é supostamente padronizado em / usr / bin (a mesma página do link sed, mas eles não me permitem criar um terceiro link para este post). E quanto a awk / gawk? Alguém sabe o que é mais comum ou popular?

user2672807
fonte
Por que você usa -f? Não é /bin/gawksuficiente? Além disso, isso pode ser relevante.
terdon

Respostas:

7

Shebang não era para ser tão flexível . Pode haver alguns casos em que ter um segundo parâmetro funcione , acho que o FreeBSD é um deles.

espera-se que o gawk e a maioria dos utilitários que acompanham o sistema operacional /usr/bin/.

Nos dias anteriores do UNIX, era comum /usr/montar sobre NFS ou alguma mídia mais barata para economizar espaço em disco local e custo por estação de trabalho. /bin/deveria ter tudo o necessário para inicializar no modo de usuário único . Como /usr/não foi montado em uma mídia confiável, /bin/incluiu utilitários suficientes para torná-la amigável o suficiente para administração geral e solução de problemas.

Isso foi herdado no Linux inicialmente, mas como o espaço em disco não é mais um problema e, na maioria dos casos, /usr/está no sistema de arquivos raiz, a tendência atual é mudar tudo /usr/bin(pelo menos no mundo do Linux). Portanto, a maioria dos utilitários instalados por uma distro deve ser encontrada lá. Mesmo o mais serviços básicos, como cp, rm, lsetc (assim, ainda não).

Em relação à escolha shebang. Tradicionalmente, isso é algo que os administradores ou usuários precisam editar de acordo com o ambiente. Pelo que todo desenvolvedor sabe, nos sistemas de outras pessoas, o intérprete pode estar em qualquer lugar do sistema de arquivos (por exemplo /usr/local/bin, /opt/gawk-4.0.1/bin). Os scripts empacotados corretamente (rpm, deb etc) vêm com uma dependência de um pacote de distribuição (por exemplo, o intérprete tem um local conhecido) ou um script de configuração que configura o hashbang apropriado durante a instalação.

forcefsck
fonte
14

Se você não precisa passar argumentos para o comando, então #!/usr/bin/env gawké o caminho a seguir, no entanto, muitos kernels (incluindo Linux) aceitam apenas um único argumento para exibir programas.

Caso contrário, você pode criar um programa poliglota que seja um invólucro de shell e o script awk. Aqui está um para awk.

#!/bin/sh
true + /; exec gawk -f "$0"; exit; / {}
# awk script starts here

Análise de shell:

  • true + /;- o comando true(que não faz nada) com dois argumentos inertes +e /.
  • A chamada para gawk. Pode ser qualquer trecho de shell que não contenha novas linhas e onde as barras são gravadas \/(o shell não se importa, exceto aspas).
    A chamada é usada execpara substituir o shell por gawk em vez de executar o gawk como um subprocesso.
  • exit;- saia do shell, caso o gawk não tenha sido encontrado. Qualquer coisa depois disso é ignorada, exceto que deve ser uma sintaxe válida do shell, caso o shell tente analisar a linha inteira antes de começar a executá-lo.

Análise do Awk:

  • O bit entre barras é uma expressão regular.
  • true + /REGEX/- uma condição. trueé uma variável indefinida, portanto seu valor numérico é 0, não que isso importe.
  • {} - Se essa condição persistir, não faça nada.
Gilles 'SO- parar de ser mau'
fonte
5

A solução proposta por Gilles é realmente uma abordagem muito boa (finalmente, tenha a reputação de votar em seu post :)).

De qualquer forma, tanto quanto eu entendo o execcomando, ele torna o processo exitapós desnecessário, inacessível, pois o processo do shell é substituído por awk.

Além disso, para permitir que o awkscript acesse seus parâmetros de chamada, sugiro algumas alterações na solução proposta:

#!/bin/sh
true + /; exec -a "$0" gawk -f "$0" -- "$@"; / {}
# awk script starts here

O -a "$0"permite que o script para ter acesso ao seu nome invocação, caso contrário, ele sempre vai ter um awkou gawkao acessar a ARGV[0]variável. Da mesma forma, o "$@"permite que o script acesse os parâmetros restantes na ARGV[1...N]matriz e o --precedente permite que o script receba -<something>argumentos sem que o Gawk os interprete.

Uma coisa a lembrar / considerar é adicionar uma exit(0);instrução no final do BEGIN { ... }bloco do awkprograma de script, caso contrário awk, ameaçará todos os parâmetros passados ​​para o script como arquivos de entrada. (Observe que não tem nada a ver com a exitinstrução que removemos da true + ...linha; essa foi uma instrução shell inacessível enquanto essa saída sugerida está no código awk).

Marcelo
fonte
O exit(0)foi muito útil! Além disso, para usuários de macos, veja esta lista: Um bom
Seamus