Verwirrung der Bash-Variablen-Interpolation

632
jordelver

Ich versuche, die Interpolation der Bash-Variablen zu verstehen.

Ich möchte readlinkden Pfad anzeigen, auf den ein Symlink verweist.

Wenn ich eine Zeichenfolge verwende, funktioniert es.

$ echo "$(readlink -- ~/.gitconfig)" /Users/jord/.dotfiles/gitconfig 

Aus irgendeinem Grund funktioniert es nicht, wenn ich versuche, eine Variable anstelle einer Zeichenfolge zu verwenden.

$ file="~/.gitconfig" $ echo "$(readlink -- $file)" 

Außer einer leeren Zeile wird nichts gedruckt.

Wenn ich dasselbe mache, aber dirnamestattdessen (als Beispiel), funktioniert die Variableninterpolation wie erwartet.

$ file="~/.gitconfig" $ echo "$(dirname -- "$file")" ~ 

Was mache ich falsch?

1
Warum `echo" $ (dirname - "$ file") "`? Warum nicht einfach 'dirname - "$ file" `? Kamil Maciorowski vor 5 Jahren 0
Kopieren und Einfügen aus einem anderen Beispiel :) jordelver vor 5 Jahren 0
Bitte sehen Sie folgendes: [Was ist los mit `echo $ (stuff)` oder `echo \` stuff \ ``?] (Https://superuser.com/q/1352850/432690) Kamil Maciorowski vor 5 Jahren 1

1 Antwort auf die Frage

3
Kamil Maciorowski

~in Anführungszeichen bleibt wörtlich ~. Der relevante Teil des Bash-Referenzhandbuchs beginnt mit

Wenn ein Wort mit einem nicht zitierten Tilde-Zeichen ( ~) beginnt ,…

Um den Unterschied zu sehen, vergleichen Sie:

file="~/.gitconfig" echo "$file" file=~/".gitconfig" echo "$file" 

In Ihrem ersten Beispiel $(…)arbeitet zuerst und ist in seinem Kontext ~nicht in Anführungszeichen gesetzt. So wird es wie erwartet erweitert.

Ihr $file, wenn es "nicht funktioniert" enthält wörtlich ~. POSIX-Standard sagt :

Die Reihenfolge der Worterweiterung lautet wie folgt:

Die Tilde-Erweiterung […], die Parametererweiterung […], die Befehlsersetzung […] und die arithmetische Erweiterung […] werden von Anfang bis Ende durchgeführt. […]

Da eine Tilde-Erweiterung vor der Parametererweiterung ausgeführt wird, wird eine Variable, deren Erweiterung erweitert wird, ~/somethingnicht weiter auf einen geeigneten Pfad erweitert.

Denken Sie daran, ~oder ~/ist das Besondere an Ihrer Shell unter Umständen aber zu (fast?) Alle anderen Werkzeug, es ist kein gültiger Pfad. Wenn es funktioniert, liegt es daran, dass die Shell zuerst ihre "Magie" ausführt und das andere Werkzeug den bereits erweiterten Pfad (wie /Users/jord) sieht .

Beachten Sie, dass die Tilde-Erweiterung in Ihrem letzten Beispiel nicht funktioniert. Sie erhalten immer noch das Literal ~und es ist zu spät, um ohne zusätzliche Tricks (wie eval) der Shell etwas dagegen tun zu können . dirnamebeschwert sich nicht, weil es mit strings funktioniert. Es ist egal, ob der angegebene Pfad gültig ist, existiert usw. Er sucht im Grunde nur nach der letzten Komponente ohne Schrägstrich und verwirft sie mit nachstehenden Schrägstrichen (falls vorhanden).

Siehe auch diese Antwort .

Vielen Dank. Das macht absolut Sinn, nachdem Sie es so gut erklärt haben. jordelver vor 5 Jahren 0