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

10

O gawk está em / bin ou / usr / bin normalmente? Eu usaria #!/usr/bin/env gawk , mas não posso usar argumentos. Agora estou usando #!/bin/gawk -f . O script é muito longo e contém muitas citações simples e trabalha com stdin.

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

Note that on many systems awk may be found in /usr/bin instead of in /bin. Caveat Emptor.

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

    
por user2672807 22.10.2013 / 20:19

3 respostas

6

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

O

gawk e a maioria dos utilitários fornecidos com o sistema operacional devem estar em /usr/bin/ .

Nos dias mais antigos do UNIX, era comum ter /usr/ montado sobre NFS ou algumas mídias menos caras para economizar espaço em disco local e custo por estação de trabalho. /bin/ deveria ter tudo 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á-lo amigável o suficiente para administração geral e solução de problemas.

Isso foi herdado inicialmente no Linux, mas como 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 é mover tudo em /usr/bin (pelo menos no mundo Linux ). Portanto, a maioria dos utilitários instalados por uma distro deve ser encontrada lá. Até mesmo os utilitários mais básicos, como cp , rm , ls etc (bem, ainda não).

Em relação à escolha do shebang. Tradicionalmente, isso é algo que os administradores ou usuários precisam editar de acordo com seu ambiente. Para todos os desenvolvedores sabem, nos sistemas de outras pessoas, o interpretador pode estar em qualquer lugar no sistema de arquivos (por exemplo, /usr/local/bin , /opt/gawk-4.0.1/bin ). Scripts apropriadamente empacotados (rpm, deb etc) vêm com uma dependência em um pacote distro (ou seja, o interpretador tem uma localização conhecida) ou um script de configuração que configura o hashbang apropriado durante a instalação.

    
por 22.10.2013 / 22:12
13

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 o Linux) aceitam apenas um único argumento para programas shebang.

Caso contrário, você pode criar um programa polyglot que seja um wrapper de shell e o script awk. Aqui está um para o 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 . Isso pode ser qualquer snippet de shell que não contenha novas linhas e onde barras são escritas \/ (o shell não se importa, exceto dentro de aspas). A chamada usa exec para substituir o shell pelo gawk em vez de executar o gawk como um subprocesso.
  • exit; - sai do shell, caso o gawk não tenha sido encontrado. Qualquer coisa depois disso é ignorada, exceto que deve ser uma sintaxe de shell válida caso o shell tente analisar a linha inteira antes de começar a executá-la.

Análise de awk:

  • O bit entre barras é uma expressão regular.
  • true + /REGEX/ - uma condição. true é uma variável indefinida, então seu valor numérico é 0, não que isso importe.
  • {} - Se a condição for válida, não faça nada.
por 23.10.2013 / 18:41
4

A solução proposta por Gilles é de fato uma ótima abordagem (finalmente ter a reputação de votar em seu post :)).

Em qualquer caso, até onde eu entendi o comando exec , ele torna o exit logo depois desnecessário, na verdade inacessível, já que o processo shell é substituído por awk .

Além disso, para permitir que o script awk acesse seus parâmetros de invocação, 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 tenha acesso a seu nome de invocação, caso contrário, ele sempre obterá um awk ou gawk ao acessar a variável ARGV[0] . Da mesma forma, o "$@" permite que o script acesse os parâmetros restantes na matriz ARGV[1...N] e o -- anterior permite que o script receba -<something> argumentos sem que o gawk os interprete para isso.

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

    
por 12.08.2014 / 03:54

Tags