W Linuksie shebang nie jest zbyt elastyczny; według wielu odpowiedzi ( odpowiedź Stephena KITT i Jörg W Mittag użytkownika ), nie ma wyznaczonego sposób przekazać wiele argumentów w shebang linii.
Nie jestem pewien, czy przyda się komukolwiek, ale napisałem krótki skrypt, aby zaimplementować brakującą funkcję. Zobacz https://gist.github.com/loxaxs/7cbe84aed1c38cf18f70d8427bed1efa .
Możliwe jest również pisanie wbudowanych obejść. Poniżej przedstawiam cztery obejścia niezależne od języka zastosowane w tym samym skrypcie testowym, a wynik każdego z nich drukowany. Przypuszczam, że skrypt jest wykonywalny i jest w /tmp/shebang
.
Zawijanie skryptu w bash heredoc wewnątrz substytucji procesu
O ile mi wiadomo, jest to najbardziej niezawodny, niezależny od języka sposób robienia tego. Pozwala przekazywać argumenty i zachowuje standardowe wejście. Wadą jest to, że tłumacz nie zna (rzeczywistej) lokalizacji pliku, który czyta.
#!/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
) "$@"
Wywoływanie echo -e 'aa\nbb' | /tmp/shebang 'arg1' 'arg2 contains spaces' 'arg3\ uses\ \\escapes\\'
wydruków:
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
Zauważ, że podstawienie procesu tworzy specjalny plik. To może nie pasować do wszystkich plików wykonywalnych. Na przykład #!/usr/bin/less
narzeka:/dev/fd/63 is not a regular file (use -f to see it)
Nie wiem, czy jest możliwe posiadanie heredoc wewnątrz podstawienia procesu w desce rozdzielczej.
Zawijanie skryptu w prosty heredoc
Krótsze i prostsze, ale nie będziesz mieć dostępu do stdin
skryptu, a interpreter musi móc odczytać i wykonać skrypt 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
Wywoływanie echo -e 'aa\nbb' | /tmp/shebang 'arg1' 'arg2 contains spaces' 'arg3\ uses\ \\escapes\\'
wydruków:
PYTHON_SCRIPT_BEGINNING
input() caused EOFError
argv[0] :: -
argv[1:] :: ['arg1', 'arg2 contains spaces', 'arg3\\ uses\\ \\\\escapes\\\\']
__debug__ :: True
PYTHON_SCRIPT_END
Użyj system()
wywołania awk, ale bez argumentów
Prawidłowo przekazuje nazwę wykonanego pliku, ale skrypt nie odbiera argumentów, które mu podajesz. Zauważ, że awk jest jedynym znanym mi językiem, którego interpreter jest domyślnie zainstalowany na Linuksie i domyślnie odczytuje instrukcje z wiersza poleceń.
#!/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")
Wywoływanie echo -e 'aa\nbb' | /tmp/shebang 'arg1' 'arg2 contains spaces' 'arg3\ uses\ \\escapes\\'
wydruków:
PYTHON_SCRIPT_BEGINNING
input() 0 :: aa
input() 1 :: bb
argv[0] :: /tmp/shebang
argv[1:] :: []
__debug__ :: False
PYTHON_SCRIPT_END
Użyj system()
wywołania awk 4.1+ , pod warunkiem, że twoje argumenty nie zawierają spacji
Fajnie, ale tylko wtedy, gdy masz pewność, że twój skrypt nie zostanie wywołany z argumentami zawierającymi spacje. Jak widać, twoje argumenty zawierające spacje zostałyby podzielone, chyba że spacje zostaną usunięte.
#!/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")
Wywoływanie echo -e 'aa\nbb' | /tmp/shebang 'arg1' 'arg2 contains spaces' 'arg3\ uses\ \\escapes\\'
wydruków:
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
W przypadku wersji awk poniżej 4.1 będziesz musiał użyć konkatenacji łańcuchów wewnątrz pętli for, patrz przykładowa funkcja https://www.gnu.org/software/gawk/manual/html_node/Join-Function.html .