Por que eu posso passar argumentos para / usr / bin / env nesse caso?

4

Eu li em outra resposta que não sou capaz de transmitir argumentos ao intérprete do que dando para /usr/bin/env :

Another potential problem is that the #!/usr/bin/env trick doesn't let you pass arguments to the interpreter (other than the name of the script, which is passed implicitly).

No entanto, parece que eu sou capaz, porque awk está quebrando quando eu não dou o -f flag e ele é corrigido quando eu dou o -f flag, usando /usr/bin/env :

Primeiro, sem o sinalizador -f :

$ cat wrap_in_quotes
#!/usr/bin/env awk
# wrap each line in quotes
# usage: wrap_in_quotes [ file ... ]
{ print "\""$0"\"" }
$ echo foobar | ./wrap_in_quotes
awk: syntax error at source line 1
 context is
     >>> . <<< /wrap_in_quotes
awk: bailing out at source line 1

Em segundo lugar, com o sinal -f :

$ vim wrap_in_quotes
$ cat wrap_in_quotes
#!/usr/bin/env awk -f
# wrap each line in quotes
# usage: wrap_in_quotes [ file ... ]
{ print "\""$0"\"" }
$ echo foobar | ./wrap_in_quotes
"foobar"
  • Então, se de acordo com o resposta vinculada Não consigo passar sinalizadores para o interpretador, por que posso transmitir o sinal -f para awk ?

Estou executando macOS :

$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.12.1
BuildVersion:   16B2657
    
por mbigras 28.04.2017 / 00:40

2 respostas

4

Alguns Unices, mais notavelmente o macOS (e no passado, o FreeBSD), permitirão isso, enquanto o Linux não.

A questão oposta: Shebang linha com '#! / usr / bin / env --argument' falha no Linux

    
por 28.04.2017 / 00:48
2

Você não pode portar vários argumentos para o interpretador. Em particular, o Linux não suporta isso.

Algumas variantes Unix suportam mais de um argumento na linha shebang. Este é o caso dos modernos sistemas FreeBSD e OSX / macOS e de alguns outros. Veja a página de portabilidade da shell de Sven Mascheck para um Tabela de comparação de variantes do Unix e muita informação histórica.

Se você quiser ter um script awk portátil, não há uma solução perfeita. #!/usr/bin/env e #!/bin/sh são as únicas linhas que são portáteis na prática: dependendo da variante Unix, awk pode estar em /bin ou /usr/bin , ou em alguns outros locais (por exemplo, /usr/xpg4/bin/awk no Solaris para obter um POSIX one - aquele em /usr/bin é para aplicativos legados). Como #!/usr/bin/env awk -f não funciona de forma portável, isso deixa #!/bin/sh . ( /bin/sh pode ser um shell Bourne legado em vez de um shell POSIX moderno, mas qualquer plataforma Unix tem algo lá na prática.) A idéia é escrever um poliglota , ou seja, um script que sh interprets como instruções para executar awk e awk interpreta como o script desejado. Isso funciona até mesmo em sistemas que não reconhecem linhas shebang, mas padronizam para sh para execução de scripts (alguns antigos combinados, ou alguma área de usuário semelhante a unix em kernels não-Unix).

#!/bin/sh
"exec" "awk" "-f" "$0" "$@" && 0 {}
… # awk script here

(Se portabilidade para antigos unices é uma preocupação, veja página de Sven Mascheck em "$@" de suporte e considere o uso de ${1+"$@"} .)

    
por 28.04.2017 / 00:51