Ich lese diesen Beitrag über die Verwendung von Funktionen in Bash-Shell-Variablen. Ich beobachte, dass man Shell-Funktionen wie folgt exportieren und in einer untergeordneten Shell ausführen muss, um sie zu verwenden:
$ export foo='() { echo "Inside function"; }'
$ bash -c 'foo'
Inside function
Ich möchte fragen, ob es möglich ist, Funktionen in Bash-Shell-Variablen so zu definieren, dass sie in der aktuellen Shell ausgeführt werden können, ohne exportieren und eine neue Shell ausführen zu müssen.
foo() { echo "Inside function"; }; foo
?$ function bar() { echo "Inside function"; } $ foo="bar" $ ${foo} Inside function $
Antworten:
Nein, das kannst du nicht.
Wenn Sie eine Funktion in der aktuellen Shell verwenden möchten, definieren Sie sie einfach und verwenden Sie sie später:
Vor dem Shellshock- Tag können Sie Funktionen in einer Variablen speichern, Variablen exportieren und Funktionen in Sub-Shell verwenden, da die
bash
Unterstützung der Exportfunktion die Funktionsdefinition in Umgebungsvariablen wiebash
folgt einfügt :Interpretieren Sie dann die Funktion, indem Sie sie durch
=
Leerzeichen ersetzen . Es besteht keine Absicht, eine Funktion in eine Variable einzufügen, und es wird auf eine Variable verwiesen, die die Funktion ausführt.Nachdem Stéphane Chazelas den Fehler gefunden hatte , wurde diese Funktion entfernt und keine Funktionsdefinition mehr in einer einfachen Umgebungsvariablen gespeichert. Jetzt werden exportierte Funktionen durch Anhängen von Präfix
BASH_FUNC_
und Suffix codiert%%
, um Konflikte mit Umgebungsvariablen zu vermeiden.bash
Der Interpreter kann nun unabhängig vom Inhalt der Variablen feststellen, ob es sich um eine Shell-Funktion handelt. Sie müssen die Funktion auch definieren und explizit exportieren, um sie in der Sub-Shell zu verwenden:Wenn Ihr Beispiel mit Ihrer aktuellen
bash
Version funktioniert hat , verwenden Sie eine anfällige Version.quelle
export
,unexport
undunset
builtins von der Bourne - Shell POSIX - kompatibel und irgendwo in dieser builtins ist die Erklärung, ich glaube anexport
.man bash
. Wenn Sie es öffnen, drücken Sie die/
Taste und verwenden Sie einen regulären^[[:space:]]*Func
Ausdruck, um eine Zeile zu finden, die mit dieser Phrase beginnt. Drücken Sien
, um Übereinstimmungen zu Ihrer Suche zu überspringen. und nach Ihrer Frage zu urteilen, möchten Sie vielleicht auch einen Blick darauf werfenalias
.}
.bash
Die Dokumentation enthält einen Detailteil über Funktionen .Eine Funktion ist schließlich einfach eine benannte, vorab analysierte statische Befehlszeichenfolge, die im Speicher der Shell gespeichert ist. Der einzige wirkliche Weg, dies zu tun, besteht darin, Zeichenfolgen als Code auszuwerten. Genau das tut die Shell jedes Mal, wenn Sie Ihre Funktion aufrufen.
Es war noch nie so anders und ist es immer noch nicht. Die Entwickler richten hierfür bequeme Methoden ein und versuchen, mögliche Sicherheitslücken so gut wie möglich zu schützen. Tatsache ist jedoch, dass je bequemer eine Sache wird, desto wahrscheinlicher ist es, dass Sie weniger darüber wissen, als Sie sollten.
Es gibt viele Optionen zur Verfügung , wenn es darum geht , Daten von den Eltern Schalen Subshells zu importieren. Machen Sie sich mit ihnen vertraut, werden Sie sicher genug, dass Sie ihre potenziellen Verwendungszwecke und ihre potenziellen Schwächen identifizieren und sie sparsam, aber effektiv einsetzen können.
Ich nehme an, ich kann ein oder zwei davon näher erläutern, während ich dabei bin. Der wahrscheinlich beste Weg, um statische Befehle von einer Shell an eine andere zu übergeben (egal ob es sich um eine untergeordnete Befehlskette handelt oder nicht), ist
alias
.alias
ist in dieser Funktion nützlich, da es POSIX-spezifiziert ist , um seine definierten Befehle sicher zu melden :Zum Beispiel:
Sehen Sie, was es dort mit den Zitaten macht? Die genaue Ausgabe hängt von der Shell ab. Im Allgemeinen können Sie sich jedoch darauf verlassen, dass eine Shell ihre
alias
Definitionen auf eine Weiseeval
meldet, die für die erneute Eingabe in dieselbe Shell sicher ist . Das Mischen und Anpassen von Quell- / Ziel-Shells kann jedoch in einigen Fällen zweifelhaft sein.Um einen Grund für diese Vorsicht aufzuzeigen:
Beachten Sie auch, dass der
alias
Namespace einen von drei unabhängigen Namespaces darstellt, von denen Sie allgemein erwarten können, dass sie in praktisch jeder modernen Shell vollständig ausgearbeitet sind. In der Regel bieten Shells diese drei Namespaces:Variablen:
name=value
außerhalb von Listenexport
,set
,readonly
in einigen Fällen.Funktionen:
name() compound_command <>any_redirects
in Befehlspositionalias
Werte, wennalias
sie im richtigen Kontext gefunden werden, beim Auffinden in den Funktionsdefinitionsbefehl erweitert werden.Aliase:
alias name=value
in Kommandopositionalias
Definitionen interpretiert, wenn die Definitionsnamen später an der Befehlsposition gefunden werden.alias
gültige Shell-Erweiterungen, die darin enthalten sind, zum definierten Zeitpunkt ebenfalls interpretiert , da ihre Definitionen Argumente für den Befehl sind. Und so werdenalias
Definitionen immer zweimal interpretiert.alias
Definitionen zur Definitionszeit überhaupt nicht analysiert, sondern es ist der Parser der Shell, der ihre Werte vor dem Parsen in eine Befehlszeichenfolge erweitert, wenn sie gefunden werden.Sie haben wahrscheinlich bemerkt, was meiner Meinung nach der Hauptunterschied zwischen einer
alias
oder einer Funktion oben ist, die der Expansionspunkt der Shell für jede Funktion ist. Die Unterschiede können ihre Kombination tatsächlich sehr nützlich machen.Dies ist ein Alias, der eine Funktion definiert, die sich beim Aufruf selbst aufhebt und daher einen Namespace durch die Anwendung eines anderen beeinflusst. Es ruft dann die Funktion auf. Das Beispiel ist naiv; In einem regulären Kontext ist es nicht sehr nützlich, aber das folgende Beispiel zeigt möglicherweise eine andere eingeschränkte Nützlichkeit, die es in anderen Kontexten bietet:
Sie sollten immer einen
alias
Namen in einer anderen Eingabezeile als der aufrufen, in der sich die Definition befindet. Dies hängt wiederum mit der Analysereihenfolge des Befehls zusammen. In Kombination können Aliase und Funktionen zusammen verwendet werden, um Informationen und Parameterarrays portabel, sicher und effektiv in und aus Subshelled-Kontexten zu verschieben.Fast ohne Beziehung, aber hier ist noch eine lustige:
Führen Sie dies an einer interaktiven Eingabeaufforderung aus, und alle Argumente, die Sie in derselben Ausführungszeile wie die Zeile, in der Sie es aufrufen, übergeben, werden als Argumente für eine Subshell interpretiert. Alle Zeilen danach bis zur ersten auftretenden Leerzeile werden jedoch von der aktuellen Shell eingelesen, um als Standard an die Subshell zu übergeben, die sie zum Aufrufen vorbereitet, und keine dieser Zeilen wird in irgendeiner Weise interpretiert.
... aber nur ...
...ist einfacher...
quelle