Por que #! / usr / bin / env mostra "$ @" como 1?

0

Se eu tiver test.sh:

#!/usr/bin/env bash
echo "$@"

bash test.sh resulta em 1

Alguma ideia do motivo pelo qual o resultado é 1? Além disso, por que shebang para env em vez de diretamente para bater?

ATUALIZAÇÃO: Desculpe, perdi algum código, o que agora tem isso, faz sentido.

#!/usr/bin/env bash
main() {
  echo ${1:-1}
}
main "$@"
    
por mellow-yellow 09.10.2018 / 13:12

2 respostas

0

Não consigo reproduzir isso no Ubuntu 18.04.1.

Você deve testar echo "$@" fora do script. Ele mostrará 1 se você já tiver digitado set 1 , ou os resultados de qualquer parâmetro posicional anterior set (inclusive nos scripts de inicialização).

Observe que bash test.sh executa test.sh como um arquivo source ( . ) e qualquer linha #! é ignorada. Para agir em !# você precisaria:

bash -c test.sh

Quanto a por que env é especificado, não tenho idéia, a menos que tenha sido adicionado como um marcador: teria um efeito se incluísse uma ou mais especificações de ambiente. Por exemplo, o seguinte especificaria bash para ser executado com um arquivo de inicialização personalizado:

!#/usr/bin/env BASH_ENV=BashStart bash
...

Outro motivo, sugerido pela resposta de Attie, é que no OSX bash por padrão não está em /bin/ , mas env está em /usr/bin/ , como no Linux, portanto !#/usr/bin/env bash permite bash ser especificado como o shell em um script que será executado no Linux ou no OSX.

    
por 09.10.2018 / 14:04
0

O " código ausente " é muito significativo.

#!/usr/bin/env bash

main() {
  echo ${1:-1}
}

main "$@"

Aqui, estamos chamando a função main e fornecendo "${@}" (ou seja, todos os nossos argumentos, mantendo a separação).

Quando ${@} se expande para nada (ou seja: o script foi invocado sem argumentos), o main() é chamado com argumentos no e, portanto, o ${1:-1} dentro do main() A função terá um efeito especial, conforme " Substituição de parâmetros "semântica.

Especificamente, ${parameter:-default} expandirá para o valor de ${parameter} se for declarado e não-NULL ou default se não for declarado ou NULL. Observe que ${parameter:-default} se comporta de maneira sutilmente diferente de ${parameter-default} .

${parameter-default} and ${parameter:-default} are almost equivalent. The extra : makes a difference only when parameter has been declared, but is null.

Assim, o ${1:-1} será expandido para o primeiro argumento ou padrão para 1 :

$ ./script.sh
1
$ ./script.sh test
test

O uso de /usr/bin/env no shebang nos permite " usar bash como o interpretador " sem fornecer o caminho completo para bash ... env pesquisaremos o atual ${PATH} do ambiente e use o primeiro candidato correspondente para nós. O shebang requer um caminho absoluto para o intérprete, e nós podemos contornar essa limitação usando env .

Isso é muito comum em scripts Python, já que o interpretador pode estar em vários locais - embora geralmente /usr/bin/python , isso suporta coisas como virtualenv também.

Veja " Por que as pessoas escrevem o #! / usr / bin / env python shebang na primeira linha de um script Python? " para mais discussões.

    
por 09.10.2018 / 15:17

Tags