Es ist höchste Zeit, dieses Rätsel zu lösen, das mich seit Jahren beschäftigt ...
Ich habe dies von Zeit zu Zeit getroffen und dachte, das ist der richtige Weg:
$(comm "$(arg)")
Und dachte, meine Ansicht wurde stark von der Erfahrung gestützt. Aber ich bin mir nicht mehr so sicher. Shellcheck kann sich auch nicht entscheiden. Es ist beides:
"$(dirname $0)"/stop.bash
^-- SC2086: Double quote to prevent globbing and word splitting.
Und:
$(dirname "$0")/stop.bash
^-- SC2046: Quote this to prevent word splitting.
Was ist die Logik dahinter?
(Es ist übrigens Shellcheck Version 0.4.4.)
bash
quoting
command-substitution
Tomasz
quelle
quelle
"$(dirname "$0")"/stop.bash
:? Es scheint zu funktionieren ... Was ist die Geschichte?shell_level_1 $(shell_level_2) shell_level_1
Sie sich das folgendermaßen vor$(....)
:: Wenn Sie sich in der Shell befinden, geben Sie eine "Unterebene" der Shell ein, ABER Sie können darin schreiben, als ob Sie sich auf der Primärebene befänden (dh Sie können direkt"
anstelle von\"
usw. schreiben ). Beispiel:touch "/tmp/a file" ; echo "its size is: $(find "/tmp/a file" -ls | awk '{print $5}) ..." : if you used backticks you'd have to
Finden Sie "/ tmp / a file" undprint \$5
. Mit$(...)
keine Notwendigkeit: die Schale passt sich an die neue Ebene und Sie können auch direkt schreiben , als ob Ihr Dolmetscher jetzt auf dieser Ebene auch.Antworten:
Sie müssen verwenden
"$(somecmd "$file")"
.Ohne die Anführungszeichen wird ein Pfad mit einem Leerzeichen im Argument für geteilt
somecmd
und auf die falsche Datei abgezielt. Sie brauchen also Zitate auf der Innenseite.Alle Leerzeichen in der Ausgabe von
somecmd
verursachen ebenfalls eine Aufteilung. Daher müssen Sie die gesamte Befehlsersetzung in Anführungszeichen setzen.Anführungszeichen innerhalb der Befehlsersetzung haben keine Auswirkung auf die Anführungszeichen außerhalb der Befehlsersetzung. Bashs eigenes Referenzhandbuch ist dazu nicht allzu klar, aber BashGuide erwähnt es ausdrücklich . Der Text in POSIX erfordert dies auch, da "jedes gültige Shell-Skript" darin zulässig ist
$(...)
:Beispiel:
ein. Keine Angebote,
dirname
verarbeitet beides./space
undhere/foo
:b. Zitate innerhalb,
dirname
Prozesse./space here/foo
, Geben./space here
, die in zwei Teile geteilt sind:c. Anführungszeichen außerhalb
dirname
verarbeiten beide./space
undhere/foo
Ausgaben in separaten Zeilen, aber jetzt bilden die beiden Zeilen ein einziges Argument :d. Zitate sowohl innerhalb als auch außerhalb, dies gibt die richtige Antwort:
(Das wäre möglicherweise einfacher gewesen, wenn
dirname
nur das erste Argument verarbeitet worden wäre, aber das würde den Unterschied zwischen den Fällen a und c nicht aufzeigen.)Beachten Sie, dass Sie mit
dirname
(und möglicherweise mit anderen) auch hinzufügen möchten, um--
zu verhindern, dass der Dateiname als Option verwendet wird, falls er mit einem Bindestrich beginnt"$(dirname -- "$file")"
. Verwenden Sie daher .quelle
$( )
wird jedoch ein neuer Kontext erstellt, sodass die darin enthaltenen Anführungszeichen unabhängig von den Anführungszeichen außerhalb des Kontexts sind. Und in der Regel möchten Sie in beiden Kontexten Zitate.