Wie entkommen ich die Wildcard / Sternchen in der Bash?
Frage
zB.
me$ FOO="BAR * BAR"
me$ echo $FOO
BAR file1 file2 file3 file4 BAR
und mit den "\" Escape-Zeichen:
me$ FOO="BAR \* BAR"
me$ echo $FOO
BAR \* BAR
Ich bin natürlich etwas zu tun dumm.
Wie bekomme ich die Ausgabe "BAR * BAR"?
Lösung
Zitiert bei $ FOO Einstellung ist nicht genug. Sie müssen die variablen Referenz auch zitieren:
me$ FOO="BAR * BAR"
me$ echo "$FOO"
BAR * BAR
Andere Tipps
SHORT ANTWORT
Wie schon andere gesagt haben - sollten Sie immer die Variablen zitieren seltsame Verhalten zu verhindern. So verwenden echo "$ foo" in anstatt nur echo $ foo .
LONG ANTWORT
Das glaube ich dieses Beispiel weitere Erklärung garantiert, weil es mehr los ist, als es auf den ersten Blick es scheinen mag.
kann ich sehen, wo Ihre Verwirrung in da kommt, nachdem Sie Ihr erstes Beispiel lief Sie wahrscheinlich zu sich selbst dachte, dass die Schale offensichtlich tut:
- Parameter Erweiterung
- Dateierweiterung
So von Ihrem ersten Beispiel:
me$ FOO="BAR * BAR"
me$ echo $FOO
Nach Parameter Expansion entspricht:
me$ echo BAR * BAR
Und nach Dateinamen Expansion entspricht:
me$ echo BAR file1 file2 file3 file4 BAR
Und wenn Sie nur echo BAR * BAR
in die Befehlszeile eingeben, werden Sie sehen, dass sie gleichwertig sind.
So werden Sie wahrscheinlich gedacht, um sich selbst „wenn ich die * entkommen, kann ich den Dateinamen Erweiterung verhindern“
So von Ihrem zweiten Beispiel:
me$ FOO="BAR \* BAR"
me$ echo $FOO
Nach Parameter Expansion sollten gleichwertig sein:
me$ echo BAR \* BAR
Und nach Dateinamen Expansion sollten gleichwertig sein:
me$ echo BAR \* BAR
Und wenn Sie versuchen, die Eingabe von „echo BAR \ * BAR“ direkt in die Befehlszeile wird es in der Tat Druck „BAR * BAR“, weil der Dateinamen Erweiterung durch das Entweichen verhindert wird.
Warum also mit $ foo nicht?
Es ist, weil es eine dritte Erweiterung ist, die stattfindet - Quote Removal. Von der bash Entfernung manuell Zitat:
Nach den vorangegangenen Erweiterungen, die alle unquoted Vorkommen der Zeichen ‚\‘, ‚'‘ Und ‚'‘, das nicht zur Folge hat aus einem der oben genannten Erweiterungen sind entfernt.
Also, was passiert, wenn Sie den Befehl direkt in die Befehlszeile eingeben, ist das Escape-Zeichen nicht das Ergebnis einer vorherigen Expansion so BASH es entfernt, bevor es den Echo-Befehl, aber im zweiten Beispiel der „\ Senden *“war das Ergebnis einer vorherigen Parameter Expansion, so ist es nicht entfernt. Als Ergebnis erhält echo „\ *“ und das ist, was es gedruckt wird.
Beachten Sie den Unterschied zwischen dem ersten Beispiel -. „*“ Ist nicht in den Zeichen enthalten, die durch Quote Removal entfernt werden
Ich hoffe, das macht Sinn. Am Ende der Abschluss in der gleichen - nur Anführungszeichen verwenden. Ich dachte, ich würde erklären, warum, zu entkommen, was logisch funktionieren sollte, wenn nur Parameter und Dateierweiterung im Spiel sind, hat nicht funktioniert.
Für eine vollständige Erklärung der BASH-Erweiterungen finden Sie unter:
http://www.gnu.org/software/ bash / manual / bashref.html # Shell-Expansions
Ich werde ein wenig zu diesem alten Thread hinzufügen.
In der Regel würden Sie verwenden
$ echo "$FOO"
Allerdings habe ich Probleme, auch mit dieser Syntax hatte. Betrachten Sie das folgende Skript.
#!/bin/bash
curl_opts="-s --noproxy * -O"
curl $curl_opts "$1"
Die *
muss wörtlich zu curl
weitergegeben werden, aber die gleichen Probleme auftreten werden. Das obige Beispiel wird nicht funktionieren (es Dateinamen im aktuellen Verzeichnis erweitern) und wird weder \*
. Sie können auch nicht $curl_opts
zitieren, weil sie als einzige (ungültig) Option erkannt wird curl
.
curl: option -s --noproxy * -O: is unknown
curl: try 'curl --help' or 'curl --manual' for more information
Deshalb würde ich die Verwendung der bash
Variable $GLOBIGNORE
empfiehlt Dateinamen Erweiterung gänzlich zu verhindern, wenn auf das globale Muster aufgebracht, oder verwenden Sie die set -f
Einbau-Flagge.
#!/bin/bash
GLOBIGNORE="*"
curl_opts="-s --noproxy * -O"
curl $curl_opts "$1" ## no filename expansion
Die Anwendung auf Ihrem ursprünglichen Beispiel:
me$ FOO="BAR * BAR"
me$ echo $FOO
BAR file1 file2 file3 file4 BAR
me$ set -f
me$ echo $FOO
BAR * BAR
me$ set +f
me$ GLOBIGNORE=*
me$ echo $FOO
BAR * BAR
FOO='BAR * BAR'
echo "$FOO"
echo "$FOO"
Es kann vielmehr mit printf
immer in die Gewohnheit wert sein dann auf der Kommandozeile echo
.
In diesem Beispiel ist es nicht viel Nutzen geben, aber es kann mit komplexeren Ausgabe nützlicher sein.
FOO="BAR * BAR"
printf %s "$FOO"