No Linux, o shebang não é muito flexível; de acordo com várias respostas (resposta de Stephen Kitt e Jörg W Mittag ), não existe uma maneira designada de passar vários argumentos em uma linha shebang.
Não tenho certeza se será útil para alguém, mas escrevi um script curto para implementar o recurso que faltava. Consulte https://gist.github.com/loxaxs/7cbe84aed1c38cf18f70d8427bed1efa .
Também é possível escrever soluções alternativas incorporadas. A seguir, apresento quatro soluções alternativas independentes de idioma aplicadas ao mesmo script de teste e o resultado é impresso. Suponho que o script é executável e é no /tmp/shebang
.
Envolvendo seu script em um heredoc bash dentro da substituição do processo
Até onde eu sei, essa é a maneira mais confiável e independente de linguagem. Permite passar argumentos e preserva stdin. A desvantagem é que o intérprete não sabe a localização (real) do arquivo que lê.
#!/bin/bash
exec python3 -O <(cat << 'EOWRAPPER'
print("PYTHON_SCRIPT_BEGINNING")
from sys import argv
try:
print("input() 0 ::", input())
print("input() 1 ::", input())
except EOFError:
print("input() caused EOFError")
print("argv[0] ::", argv[0])
print("argv[1:] ::", argv[1:])
print("__debug__ ::", __debug__)
# The -O option changes __debug__ to False
print("PYTHON_SCRIPT_END")
EOWRAPPER
) "$@"
Chamando echo -e 'aa\nbb' | /tmp/shebang 'arg1' 'arg2 contains spaces' 'arg3\ uses\ \\escapes\\'
impressões:
PYTHON_SCRIPT_BEGINNING
input() 0 :: aa
input() 1 :: bb
argv[0] :: /dev/fd/62
argv[1:] :: ['arg1', 'arg2 contains spaces', 'arg3\\ uses\\ \\\\escapes\\\\']
__debug__ :: False
PYTHON_SCRIPT_END
Observe que a substituição do processo produz um arquivo especial. Isso pode não ser adequado a todos os executáveis. Por exemplo, #!/usr/bin/less
reclama:/dev/fd/63 is not a regular file (use -f to see it)
Não sei se é possível ter o heredoc dentro da substituição do processo no hífen.
Envolvendo seu script em um heredoc simples
Mais curto e mais simples, mas você não poderá acessar stdin
do seu script e exige que o intérprete possa ler e executar um script stdin
.
#!/bin/sh
exec python3 - "$@" << 'EOWRAPPER'
print("PYTHON_SCRIPT_BEGINNING")
from sys import argv
try:
print("input() 0 ::", input())
print("input() 1 ::", input())
except EOFError:
print("input() caused EOFError")
print("argv[0] ::", argv[0])
print("argv[1:] ::", argv[1:])
print("__debug__ ::", __debug__)
# The -O option changes __debug__ to False
print("PYTHON_SCRIPT_END")
EOWRAPPER
Chamando echo -e 'aa\nbb' | /tmp/shebang 'arg1' 'arg2 contains spaces' 'arg3\ uses\ \\escapes\\'
impressões:
PYTHON_SCRIPT_BEGINNING
input() caused EOFError
argv[0] :: -
argv[1:] :: ['arg1', 'arg2 contains spaces', 'arg3\\ uses\\ \\\\escapes\\\\']
__debug__ :: True
PYTHON_SCRIPT_END
Use system()
chamada awk, mas sem argumentos
Passa corretamente o nome do arquivo executado, mas seu script não receberá os argumentos que você fornecer. Observe que o awk é o único idioma que conheço cujo intérprete está instalado no linux por padrão e lê suas instruções na linha de comando por padrão.
#!/usr/bin/gawk BEGIN {system("python3 -O " ARGV[1])}
print("PYTHON_SCRIPT_BEGINNING")
from sys import argv
print("input() 0 ::", input())
print("input() 1 ::", input())
print("argv[0] ::", argv[0])
print("argv[1:] ::", argv[1:])
print("__debug__ ::", __debug__)
# The -O option changes __debug__ to False
print("PYTHON_SCRIPT_END")
Chamando echo -e 'aa\nbb' | /tmp/shebang 'arg1' 'arg2 contains spaces' 'arg3\ uses\ \\escapes\\'
impressões:
PYTHON_SCRIPT_BEGINNING
input() 0 :: aa
input() 1 :: bb
argv[0] :: /tmp/shebang
argv[1:] :: []
__debug__ :: False
PYTHON_SCRIPT_END
Use a system()
chamada awk 4.1+ , desde que seus argumentos não contenham espaços
Bom, mas apenas se você tiver certeza de que seu script não será chamado com argumentos que contenham espaços. Como você pode ver, seus argumentos que contêm espaços seriam divididos, a menos que os espaços sejam escapados.
#!/usr/bin/gawk @include "join"; BEGIN {system("python3 -O " join(ARGV, 1, ARGC, " "))}
print("PYTHON_SCRIPT_BEGINNING")
from sys import argv
print("input() 0 ::", input())
print("input() 1 ::", input())
print("argv[0] ::", argv[0])
print("argv[1:] ::", argv[1:])
print("__debug__ ::", __debug__)
# The -O option changes __debug__ to False
print("PYTHON_SCRIPT_END")
Chamando echo -e 'aa\nbb' | /tmp/shebang 'arg1' 'arg2 contains spaces' 'arg3\ uses\ \\escapes\\'
impressões:
PYTHON_SCRIPT_BEGINNING
input() 0 :: aa
input() 1 :: bb
argv[0] :: /tmp/shebang
argv[1:] :: ['arg1', 'arg2', 'contains', 'spaces', 'arg3 uses \\escapes\\']
__debug__ :: False
PYTHON_SCRIPT_END
Para versões awk abaixo de 4.1, você precisará usar a concatenação de strings dentro de um loop for, veja a função de exemplo https://www.gnu.org/software/gawk/manual/html_node/Join-Function.html .