Skriptfunktionsaufruf: Funktion vs. $(Funktion)

Skriptfunktionsaufruf: Funktion vs. $(Funktion)

Der Einfachheit halber verweisen wir auf den folgenden Code.

#!/bin/bash

number=7

function doSomething() {
  number=8
}

doSomething
echo "$number"

Es druckt 8.

Aber mit:

#!/bin/bash

number=7

function doSomething() {
  number=8
}

$(doSomething)
echo "$number"

Es druckt 7.

Ich habe folgende Fragen:

  • Was sind dietechnische Namenfür jeden?, ich meine functioncallund$(functioncall)
  • Wie funktioniert jeder Ansatz? Es scheint, dass ersterer die Variablen außerhalb der Funktion selbst berücksichtigt (beeinflusst), letzterer nicht
  • Wenn es zwingend erforderlich ist, einen Ansatz dem anderen vorzuziehen (meistens geht es natürlich um Leistungsprobleme, falls es welche gibt), sind andere Gründe willkommen.

Antwort1

Sie erleben die Feinheiten der Befehlssubstitution.

Der Anruf

doSomething

ist ein einfacher Funktionsaufruf. Er führt die Funktion aus, so als ob Sie die Befehle der Funktion kopiert und an die Stelle eingefügt hätten, an der Sie sie aufrufen. Dabei überschreibt er die Variable numbermit dem neuen Wert 8.

Der Anruf

$(doSomething)

auf der anderen Seite ist einBefehlsersetzung. Es ist dazu gedacht, die Funktion auszuführen undgibt den Inhalt der ausgegebenen Funktion zurück stdout. Es wird normalerweise nicht "standalone" verwendet, sondern in Variablenzuweisungen, z. B.

os_type=$(uname)

Dadurch wird der Befehl ausgeführt uname, der auf einem Linux-System auf der Konsole ausgegeben wird Linux, und das Ergebnis wird in der Shell-Variable gespeichert os_type. Daher ist es nicht sinnvoll, einen Befehlsersatz mit einem Befehl oder einer Funktion zu verwenden, die nichts ausgibt, wie Ihr doSomething. Da der Ersatz $(doSomething)im Grunde ein Platzhalter für die Ausgabe von ist doSomething, besteht der einzige Grund, warum Sie dort keinen Skriptfehler erhalten, darin, dass Ihre Funktion nichts ausgibt. Hätten Sie beispielsweise angegeben,

$(uname)

anstatt

$(doSomething)

Ihre Shell hätte versucht, den Befehl auszuführen Linuxund eine

Linux: No such file or directory

Fehler (1) .

Der Schlüssel zum Verständnis des beobachteten Effekts ist, dass bei einer Befehlssubstitutionder Befehl wird in einer Subshell ausgeführt, d. h. alle an Variablen vorgenommenen Änderungen werden nicht an die Shell zurückpropagiert, in der Sie das Hauptskript ausführen. Während es intern die Befehle von ausführt doSomethingund eine Variable numberauf setzt 8, geschieht dies in seinem eigenen Shell-Prozess, der nichts mit dem Shell-Prozess zu tun hat, der Ihr Skript ausführt (abgesehen davon, dass es stdoutabgerufen wird), und kann daher die Variable, numberdie Sie im Hauptskript verwendet haben, nicht ändern.

Weitere Informationen finden Sie unter

hier auf dieser Site oder

für mehr Übersicht.


(1) Andererseits bedeutet dies, dass Sie durch eine Befehlsersetzung einen Befehl ausführen können, dessen Namen Sie beim Schreiben des Skripts noch nicht kennen, den Sie aber durch Ausführen eines anderen, Ihnen bekannten Befehls herausfinden können.

verwandte Informationen