Ich muss eine Funktion als Parameter in Bash übergeben. Zum Beispiel der folgende Code:
function x() {
echo "Hello world"
}
function around() {
echo "before"
eval $1
echo "after"
}
around x
Sollte ausgeben:
before
Hello world
after
Ich weiß, dass dies eval
nicht korrekt ist, aber das ist nur ein Beispiel :)
Irgendeine Idee?
function
Wort behalten , können Sie erst dann auf diese internen Methoden zugreifen, wenn Sie die Methode der obersten Ebene ausführen.Ich glaube nicht, dass jemand die Frage ganz beantwortet hat. Er fragte nicht, ob er die Saiten in der richtigen Reihenfolge wiedergeben könne. Vielmehr möchte der Autor der Frage wissen, ob er das Verhalten von Funktionszeigern simulieren kann.
Es gibt einige Antworten, die meinen Vorstellungen sehr ähnlich sind, und ich möchte sie um ein weiteres Beispiel erweitern.
Vom Autor:
Um dies zu erweitern, wird die Funktion x echo "Hello world: $ 1" angezeigt, um anzuzeigen, wann die Funktionsausführung tatsächlich erfolgt. Wir werden eine Zeichenfolge übergeben, die der Name der Funktion "x" ist:
Um dies zu beschreiben, wird die Zeichenfolge "x" an die Funktion around () übergeben, die "before" wiedergibt, die Funktion x (über die Variable $ 1, den ersten Parameter, der an around übergeben wird) aufruft und das Argument "HERE" übergibt .
Abgesehen davon ist dies die Methode, um Variablen als Funktionsnamen zu verwenden. Die Variablen enthalten tatsächlich die Zeichenfolge, die der Name der Funktion ist, und ($ variable arg1 arg2 ...) ruft die Funktion auf, die die Argumente übergibt. Siehe unten:
ergibt: 30 10 20, wobei wir die in der Variablen Z gespeicherte Funktion "x" ausgeführt und die Parameter 10 20 und 30 übergeben haben.
Oben, wo wir Funktionen referenzieren, indem wir den Funktionen Variablennamen zuweisen, damit wir die Variable verwenden können, anstatt den Funktionsnamen tatsächlich zu kennen (ähnlich wie Sie es in einer sehr klassischen Funktionszeigersituation in c tun könnten, um den Programmfluss zu verallgemeinern, aber vor - Auswahl der Funktionsaufrufe, die Sie basierend auf Befehlszeilenargumenten ausführen).
In Bash sind dies keine Funktionszeiger, sondern Variablen, die sich auf Namen von Funktionen beziehen, die Sie später verwenden.
quelle
()
startet das nicht eine Sub-Shell?es besteht keine Notwendigkeit zu verwenden
eval
quelle
Sie können nichts anderes als Zeichenfolgen an eine andere Funktion übergeben. Prozessersetzungen können es irgendwie vortäuschen. Bash neigt dazu, das FIFO offen zu halten, bis ein Befehl abgeschlossen ist.
Hier ist eine kurze dumme
Funktionen können exportiert werden, dies ist jedoch nicht so interessant, wie es zunächst erscheint. Ich finde es hauptsächlich nützlich, um Debugging-Funktionen für Skripte oder andere Programme, die Skripte ausführen, zugänglich zu machen.
id
Es wird immer noch nur eine Zeichenfolge abgerufen, die zufällig der Name einer Funktion (automatisch aus einer Serialisierung in der Umgebung importiert) und deren Argumente ist.Der Kommentar von Pumbaa80 zu einer anderen Antwort ist ebenfalls gut (
eval $(declare -F "$1")
), aber hauptsächlich für Arrays nützlich, nicht für Funktionen, da sie immer global sind. Wenn Sie dies innerhalb einer Funktion ausführen würden, würde es nur neu definiert, sodass es keine Auswirkungen gibt. Es kann nicht verwendet werden, um Abschlüsse oder Teilfunktionen oder "Funktionsinstanzen" zu erstellen, abhängig davon, was im aktuellen Bereich gebunden ist. Bestenfalls kann dies verwendet werden, um eine Funktionsdefinition in einer Zeichenfolge zu speichern, die an anderer Stelle neu definiert wird - aber diese Funktionen können auch nur fest codiert werden, es sei denn natürlicheval
verwendet werdenGrundsätzlich kann Bash nicht so verwendet werden.
quelle
Ein besserer Ansatz ist die Verwendung lokaler Variablen in Ihren Funktionen. Das Problem wird dann, wie Sie das Ergebnis zum Anrufer erhalten. Ein Mechanismus ist die Verwendung der Befehlssubstitution:
Hier wird das Ergebnis an stdout ausgegeben und der Aufrufer verwendet die Befehlssubstitution, um den Wert in einer Variablen zu erfassen. Die Variable kann dann nach Bedarf verwendet werden.
quelle
Sie sollten etwas in der Art haben:
Sie können dann anrufen
around x
quelle
eval ist wahrscheinlich der einzige Weg, dies zu erreichen. Der einzige wirkliche Nachteil ist der Sicherheitsaspekt, da Sie sicherstellen müssen, dass nichts Bösartiges weitergegeben wird und nur Funktionen aufgerufen werden, die aufgerufen werden sollen (zusammen mit der Überprüfung, dass keine bösen Zeichen wie ';' vorhanden sind). auch darin).
Wenn Sie also derjenige sind, der den Code aufruft, ist eval wahrscheinlich der einzige Weg, dies zu tun. Beachten Sie, dass es andere Formen der Bewertung gibt, die wahrscheinlich auch mit Unterbefehlen ($ () und ``) funktionieren würden, aber sie sind nicht sicherer und teurer.
quelle
eval $1
eine Funktion mitif declare -F "$1" >/dev/null; then eval $1; fi
eval $(declare -F "$1")