2011-01-07 8 views
9

Soweit ich weiß, gibt es zwei Möglichkeiten, lokale Variablen in einer bash-Funktion zu erstellen: Erstellen Sie eine Subshell oder deklarieren Sie jede Variable als lokal.Lokale Variablen in bash: local vs. subshell

Zum Beispiel:

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

oder

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

Obvisously die Version der Sub-Shell mit einfacher ist zu schreiben, weil Sie müssen nicht interessieren alle Variablen lokal deklarieren (ganz zu schweigen (Umgebungsvariablen), die von Tools wie getopts) erstellt/exportiert werden. Aber ich könnte mir vorstellen, dass das Erstellen einer Subshell einen Overhead hat.

Also, was ist der bessere Ansatz? Was sind die Vor-/Nachteile?

+0

verlassen wird, laufen auch die 'Time' Befehl über 1000 Tests und finden Ich denke, es ist klein bis nicht existent. – Anders

Antwort

9

Das Erstellen einer Untershell beinhaltet eine fork(), so hat es definitiv Overhead im Vergleich zu einer lokalen Variablen. Während Sub-Shells billig sind — Sie sorgen sich nicht um ihre Kosten, wenn Sie eine — benötigen, sind sie nicht frei.

Wenn Ihr Skript stark beansprucht wird und die Leistung wirklich wichtig ist (so dass Hunderte von Benutzern gleichzeitig mehrere Male am Tag ausgeführt werden), können Sie sich über die Leistungskosten des Systems Sorgen machen Unterschale. OTOH, wenn Sie es einmal im Monat ausführen und das Skript als Ganzes für weniger als 10 Sekunden läuft, würden Sie wahrscheinlich nicht.

jedoch in Bezug auf Klarheit, ist es viel besser, explizit und erklären die Variablen — es das Risiko des Skripts reduziert brechen, weil jemand kommt und sagt: „diese Unterschale eindeutig nicht erforderlich ist“ (und es ist wirklich nicht, ich würde die Unterschalen von Ihren Funktionen entfernen wollen).

Schauen Sie sich die Entwicklung von Perl-Skripten an. Sie begannen mit allen Variablen, die bei Bedarf entstehen. Sie sind allmählich rigoroser geworden, und der normale Stil besteht jetzt darin, alle Variablen vorherzusagen. Bis zu einem gewissen Grad haben Shells einen ähnlichen Weg verfolgt, aber nicht so streng wie Perl. Awk ist auch eine interessante Fallstudie; Seine Funktionen verwenden globale Variablen, es sei denn, sie sind Argumente für die Funktion, was dazu führt, dass Funktionen mit 3 aktiven Argumenten (sagen wir mal) und 5 inaktiven Argumenten geschrieben werden, die effektiv lokale Variablen definieren. Es ist etwas exzentrisch, obwohl es 'funktioniert'.

0

Jetzt ist es ziemlich schwierig, sicherzustellen, dass alle Funktionen immer alle Variablen als lokal deklarieren.

Ich denke, dies ist sehr fehleranfällig ist und bevorzugen immer Subshell-Funktionen verwenden:

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

Keine Notwendigkeit, lokale Variablen zu erklären - aber auch keine Möglichkeit, globale Variablen zu ändern. Was meiner Meinung nach GUT ist!

Eine weitere Konsequenz ist, dass Sie immer den Return/Exit-Code solcher Funktionen überprüfen und entsprechend handeln müssen! Dies liegt daran, dass Sie Ihr Skript nicht innerhalb einer Subshell-Funktion beenden können!

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

f 
echo "Did not exit" 

Dies wird nicht Ihr Skript beenden. Sie müssen es auf diese Weise tun: „Aber ich könnte mir vorstellen, dass eine Sub-Shell die Schaffung eines Overhead“

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

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

Diese