Obsługiwana jest klasyczna skorupa Bourne'a, a skorupa Bash i Korn nadal obsługują -k
opcję. Gdy ma to zastosowanie, wszelkie „ dd
podobne” opcje polecenia w dowolnym miejscu wiersza poleceń są automatycznie konwertowane na zmienne środowiskowe przekazywane do polecenia:
$ set -k
$ echo a=1 b=2 c=3
$
Nieco trudniej jest przekonać, że są to zmienne środowiskowe; uruchomienie tego działa dla mnie:
$ set -k
$ env | grep '^[a-z]=' # No environment a, b, c
$ bash -c 'echo "Args: $*" >&2; env' a=1 b=2 c=3 | grep '^[a-z]='
Args:
a=1
b=2
c=3
$ set +k
$ bash -c 'echo "Args: $*" >&2; env' a=1 b=2 c=3 | grep '^[a-z]='
Args: b=2 c=3
$
Pierwszy env | grep
pokazuje brak zmiennych środowiskowych z pojedynczą małą literą. Pierwszy bash
pokazuje, że do skryptu nie są przekazywane argumenty -c
, a środowisko zawiera trzy jednoliterowe zmienne. set +k
Anuluje -k
i pokazuje, że ta sama komenda ma teraz argumenty przekazywane do niej. ( a=1
Traktowano to jak $0
scenariusz; można to również udowodnić za pomocą odpowiedniego echa).
Uzyskuje się to, o co pyta pytanie - pisanie ./script.sh a=1 b=2
powinno być takie samo jak pisanie a=1 b=2 ./script.sh
.
Pamiętaj, że napotkasz problemy, jeśli wypróbujesz takie sztuczki w skrypcie:
if [ -z "$already_invoked_with_minus_k" ]
then set -k; exec "$0" "$@" already_invoked_with_minus_k=1
fi
"$@"
Traktuje dosłownie; nie jest ponownie analizowany w celu znalezienia zmiennych w stylu przypisania (zarówno w, jak bash
i ksh
). Próbowałem:
#!/bin/bash
echo "BEFORE"
echo "Arguments:"
al "$@"
echo "Environment:"
env | grep -E '^([a-z]|already_invoked_with_minus_k)='
if [ -z "$already_invoked_with_minus_k" ]
then set -k; exec "$0" "$@" already_invoked_with_minus_k=1
fi
echo "AFTER"
echo "Arguments:"
al "$@"
echo "Environment:"
env | grep -E '^([a-z]|already_invoked_with_minus_k)='
unset already_invoked_with_minus_k
i tylko already_invoked_with_minus_k
zmienna środowiskowa jest ustawiona w exec
skrypcie 'd.