Zmienne środowiskowe zawierające funkcje to hash. Zsh nie ma nic podobnego. Możesz zrobić coś podobnego za pomocą kilku linii kodu. Zmienne środowiskowe zawierają ciągi; starsze wersje bash, zanim Shellshock został wykryty, zapisywały kod funkcji w zmiennej, której nazwa to nazwa funkcji, a po której wartości () {
następuje kod funkcji, po której następuje }
. Możesz użyć następującego kodu, aby zaimportować zmienne z tym kodowaniem i spróbować uruchomić je z ustawieniami podobnymi do bash. Zauważ, że zsh nie może emulować wszystkich funkcji bash, wszystko co możesz zrobić, to podejść nieco bliżej (np. Aby $foo
podzielić wartość i rozwinąć symbole wieloznaczne oraz ustawić tablice na 0).
bash_function_preamble='
emulate -LR ksh
'
for name in ${(k)parameters}; do
[[ "-$parameters[name]-" = *-export-* ]] || continue
[[ ${(P)name} = '() {'*'}' ]] || continue
((! $+builtins[$name])) || continue
functions[$name]=$bash_function_preamble${${${(P)name}#"() {"}%"}"}
done
(Jak zauważył Stéphane Chazelas , oryginalny odkrywca Shellshock, wcześniejsza wersja tej odpowiedzi mogłaby w tym momencie wykonać dowolny kod, gdyby definicja funkcji była zniekształcona. Ta wersja nie, ale oczywiście po wykonaniu dowolnego polecenia, może to być funkcja importowana ze środowiska).
Wersje bash po wydaniu powłoki kodują funkcje w środowisku przy użyciu niepoprawnych nazw zmiennych (np BASH_FUNC_myfunc%%
.). To sprawia, że trudniej jest je niezawodnie parsować, ponieważ zsh nie udostępnia interfejsu do wyodrębnienia takich zmiennych ze środowiska.
Nie polecam tego robić. Poleganie na funkcjach eksportowanych w skryptach jest złym pomysłem: stwarza niewidoczną zależność w twoim skrypcie. Jeśli kiedykolwiek uruchomisz skrypt w środowisku, które nie ma twojej funkcji (na innym komputerze, w zadaniu cron, po zmianie plików inicjujących powłokę,…), twój skrypt nie będzie już działał. Zamiast tego przechowuj wszystkie funkcje w jednym lub kilku osobnych plikach (coś w rodzaju ~/lib/shell/foo.sh
) i uruchom skrypty, importując funkcje, których używa ( . ~/lib/shell/foo.sh
). W ten sposób, jeśli zmodyfikujesz foo.sh
, możesz łatwo wyszukać, które skrypty na nim polegają. Jeśli skopiujesz skrypt, możesz łatwo dowiedzieć się, jakie pliki pomocnicze on potrzebuje.
Zsh (i ksh przed nim) czyni to wygodniejszym, zapewniając sposób automatycznego ładowania funkcji w skryptach, w których są one używane. Ograniczeniem jest to, że możesz umieścić tylko jedną funkcję na plik. Zadeklaruj funkcję jako automatycznie ładowaną i umieść definicję funkcji w pliku, którego nazwa jest nazwą funkcji. Umieść ten plik w katalogu wymienionym w $fpath
(który możesz skonfigurować za pomocą FPATH
zmiennej środowiskowej). W skrypcie deklaruj funkcje ładowane automatycznie autoload -U foo
.
Ponadto zsh może kompilować skrypty, aby zaoszczędzić czas analizy. Wywołanie w zcompile
celu skompilowania skryptu. Spowoduje to utworzenie pliku z .zwc
rozszerzeniem. Jeśli ten plik jest obecny autoload
, załaduje skompilowany plik zamiast kodu źródłowego. Za pomocą tej zrecompile
funkcji można (ponownie) skompilować wszystkie definicje funkcji w katalogu.