Was ist diese Formularvariable = $ (…)

9

Was bedeutet folgendes:

basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")

Ich interessiere mich besonders für diesen Teil:

varible=$(...)

Ich weiß, dass Klammern verwendet werden, um einen Unterprozess auszuführen, aber was ist, wenn sie zusammen mit verwendet werden $?

Maxim Koretskyi
quelle
3
Wenn Sie bash verwenden: Schauen Sie in die Manpage über man bashund suchen Sie nach
Befehlsersetzung

Antworten:

16

Aus dem Bash-Handbuch ( man bash):

   Befehlsersetzung
       Durch die Befehlsersetzung kann die Ausgabe eines Befehls die ersetzen
       Befehlsname. Es gibt zwei Formen:

              $ (Befehl)
       oder
              `Befehl`

       Bash führt die Erweiterung durch, indem der Befehl in einer Subshell ausgeführt wird
       Umgebung und Ersetzen der Befehlsersetzung durch den Standard
       Ausgabe des Befehls, wobei alle nachfolgenden Zeilenumbrüche gelöscht werden. Eingebettet
       Zeilenumbrüche werden nicht gelöscht, können jedoch während des Wortes entfernt werden
       spalten. Die Befehlssubstitution $ (cat-Datei) kann durch die ersetzt werden
       äquivalent aber schneller $ (<Datei).

(Dies gilt für alle Bourne-wie Muscheln, dh sh, ksh, zsh, bashetc. und zshist zu erfassen Daten mit eingebetteten NUL - Zeichen auf diese Weise auch in der Lage)

Der Befehl

basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")

weist der Variablen den Namen des Verzeichnisses zu, in dem sich das Skript befindet (und ändert gleichzeitig alle umgekehrten Schrägstriche in Schrägstriche) basedir. Alle Fehler, Warnungen oder sonstigen Diagnosemeldungen, die an den Standardfehlerstrom ausgegeben werden, werden weiterhin auf dem Terminal angezeigt ( $(...)erfasst nur die Standardausgabe des Befehls).

Die Shell beginnt mit der Ausführung der innersten Befehlssubstitution:

echo "$0" | sed -e 's,\\,/,g'

Die Ausgabe davon wird als Zeichenfolge angegeben dirname, und die Ausgabe davon wird der Variablen zugewiesen basedir.

Die doppelten Anführungszeichen dienen dazu, sicherzustellen, dass keine Wortteilung oder Dateinamen-Globbing durchgeführt wird. Andernfalls kann es vorkommen, dass das Skript fehlschlägt oder eine seltsame Ausgabe erzeugt, wenn $0(der Name des Skripts einschließlich des Pfads, der zur Ausführung verwendet wird) ein Leerzeichen enthält Zeichen oder ein Dateiname Globbing-Zeichen (wie ?oder *).

Im Allgemeinen ist es eine gute Idee, immer Erweiterungen (variable Erweiterungen, Befehlssubstitutionen und arithmetische Erweiterungen) anzugeben. In dieser Frage und ihren Antworten finden Sie eine hervorragende Erklärung, warum dies eine gute Idee ist.

Wenn das Skript als ausgeführt wurde

$ /usr/local/bin/script.sh

dann basedirwird der Wert von erhalten /usr/local/bin.

Oder auf Cygwin:

$ bash c:\\Users\\Me\\script.sh

dann basedirwird der Wert von erhalten c:/Users/Me. Die doppelten Backslashes in der Befehlszeile dienen in diesem Fall nur dazu, die einzelnen Backslashes aus der Shell zu entfernen. Der tatsächliche Wert von $0ist c:\Users\Me\script.sh.

Eine andere Möglichkeit, dasselbe zu tun, ohne es zu verwenden dirname, echound sedwäre

basedir="${0//\\//}"
basedir="${basedir%/*}"
Kusalananda
quelle
danke, also beginnt es im Grunde aus der innersten Klammer zu analysieren, richtig? und warum werden die Anführungszeichen verwendet?
Maxim Koretskyi
@ Maximus Richtig. Ich habe meine Antwort mit weiteren Informationen aktualisiert.
Kusalananda
Vielleicht sollten Sie sagen "gilt für alle Bourne-ähnlichen Muscheln". Ein bisschen klarer auf diese Weise
Sergiy Kolodyazhnyy
@Serg, beachten Sie, dass die Bourne-Shell (wie die /bin/shvon Solaris 10 oder früher) nicht unterstützt wurde $(...).
Stéphane Chazelas
@ StéphaneChazelas Ich werde dies einbauen.
Kusalananda
6

Es bedeutet , zu laufen , was innerhalb der ist Klammern in einer Sub - Shell und zurückgeben , dass als Wert , in Ihrem Fall zuweisen , dass zu varible.

marc
quelle
5

Die varible=$(..)aufgerufene Befehlssubstitution bedeutet nichts weiter, als einen Shell-Befehl auszuführen und seine Ausgabe in einer Variablen zu speichern oder mit dem Befehl echo zurück anzuzeigen. Zeigen Sie beispielsweise Datum und Uhrzeit an:

echo "Today is $(date)"

und zum Speichern in einer Variablen:

SERVERNAME=$(hostname)

Für weitere Informationen: https://www.cyberciti.biz/faq/unix-linux-bsd-appleosx-bash-assign-variable-command-output/

Wissam Roujoulah
quelle