2011-01-07 26 views
9

O ile mi wiadomo, istnieją dwa sposoby tworzenia zmiennych lokalnych w funkcji bash: tworzenie podpowłoki lub deklarowanie każdej zmiennej jako lokalnej.Zmienne lokalne w bash: local vs subshell

Na przykład:

# using local 
function foo 
{ 
    local count 
    for count in $(seq 10) 
    do 
    echo $count 
    done 
} 

lub

# using subshell 
function foo 
{ 
    (
    for count in $(seq 10) 
    do 
     echo $count 
    done 
) 
} 

Obvisously wersja używania powłoki w tle jest prostsze napisać, ponieważ nie trzeba się martwić o deklarowania wszystkich zmiennych lokalnych (nie wspominając (środowisko) utworzone/wyeksportowane przez narzędzia takie jak getopts). Ale mogę sobie wyobrazić, że tworzenie podpowłoki ma narzut.

Jakie jest lepsze podejście? Jakie są zalety/wady?

+0

, dobrze uruchomić polecenie 'oddać porównywalnych towarów ponad 1000 testów i znaleźć narzut, myślę, że jest mały, by nie istnieć. – Anders

Odpowiedz

9

Tworzenie podpowłoki obejmuje fork(), więc zdecydowanie ma narzut w porównaniu ze zmienną lokalną. Podczas gdy sub-powłoki są tanie — nie martw się o ich koszt, gdy potrzebujesz jednego —, nie są one darmowe.

Jeśli twój skrypt będzie mocno wykorzystywany, a wydajność ma naprawdę duże znaczenie (dzięki czemu będziesz mieć setki użytkowników, które jednocześnie uruchamiają go w tym samym czasie, wiele razy dziennie), możesz martwić się kosztami podrzędna. OTOH, jeśli uruchamiasz go raz w miesiącu, a cały skrypt działa przez mniej niż 10 sekund, prawdopodobnie nie.

Jednakże, jeśli chodzi o klarowność, znacznie lepiej jest jawnie i deklarować zmienne — zmniejsza to ryzyko zerwania skryptu, ponieważ ktoś przychodzi i mówi "ta podpowłokka wyraźnie nie jest potrzebna" (i tak naprawdę nie jest, chciałbym usunąć powłoki podrzędne z twoich funkcji).

Zobacz ewolucję skryptów Perla. Zaczynali jako free-for-all ze zmiennymi pojawiającymi się na żądanie. Stopniowo stają się one bardziej rygorystyczne, a normalny styl polega na wstępnym określaniu wszystkich zmiennych. Do pewnego stopnia muszle podążały podobną ścieżką, ale nie tak rygorystycznie jak Perl. Awk jest również interesującym studium przypadku; jego funkcje używają zmiennych globalnych, chyba że są argumentami funkcji, co prowadzi do zapisywania funkcji z 3 aktywnymi argumentami (np.) i 5 nieaktywnymi argumentami, które skutecznie definiują zmienne lokalne. Jest nieco ekscentryczny, choć "działa".

0

Teraz upewnienie się, że wszystkie funkcje zawsze deklarują wszystkie zmienne jako lokalne, jest dość trudne.

myślę, że to jest bardzo podatne na błędy i wolą, aby zawsze używać podpowłoki-funkcje:

f() (
echo "we are a subshell" 
) 

Nie trzeba zadeklarować zmienne lokalne - ale też nie da się zmienić zmienne globalne. Co jest DOBRE w mojej opinii!

Dodatkową konsekwencją jest to, że zawsze należy sprawdzić kod powrotu/wyjścia dla takich funkcji i odpowiednio postępować! Dzieje się tak, ponieważ nie można wyjść z skryptu z poziomu funkcji podpowstania!

f() (
    echo "Trying to exit" 
    exit 1 
) 

f 
echo "Did not exit" 

To NIE spowoduje zamknięcia skryptu. Trzeba to zrobić w ten sposób: „Ale mogę sobie wyobrazić, że stworzenie podpowłoce ma narzut”

f() (
    echo "Trying to exit" 
    exit 1 
) 

f || exit $? 
echo "Did not exit" 

to wyjdzie