Bashs elegante Schlichtheit scheint sich in der riesigen Manpage zu verlieren.
Zusätzlich zu den oben genannten hervorragenden Lösungen würde ich versuchen, Ihnen einen Spickzettel zu geben, wie bash Anweisungen analysiert und interpretiert . Anhand dieser Roadmap analysiere ich dann die vom Fragesteller vorgestellten Beispiele, damit Sie besser verstehen, warum sie nicht wie beabsichtigt funktionieren.
Hinweis: Shell-Skriptzeilen werden direkt verwendet. Eingegebene Eingabezeilen werden zunächst in der Historie erweitert.
Jede Bash-Zeile wird zuerst mit einem Token versehen oder mit anderen Worten in sogenannte Token zerlegt . (Das Token wird vor allen anderen Erweiterungen ausgeführt, einschließlich geschweifte Klammer, Tilde, Parameter, Befehl, Arithmetik, Prozess, Wortteilung und Dateinamenerweiterung.)
Ein Token bedeutet hier einen Teil der Eingabezeile, der durch eines der folgenden speziellen Metazeichen getrennt ist:
space, - White space...
tab,
newline,
‘<’, - Redirection & piping...
‘|’,
‘>’
‘&’, - And/Both < | > | >> .or. &<file descriptor>
‘;’, - Command termination
‘(’, - Subshell, closed by - ‘)’
Bash verwendet viele andere Sonderzeichen, aber nur diese 10 erzeugen die ersten Token.
Da diese Metazeichen jedoch manchmal auch in einem Token verwendet werden müssen, muss es eine Möglichkeit geben, ihre spezielle Bedeutung zu beseitigen. Dies nennt man Flucht. Entweichenden erfolgte entweder durch eine Kette von einem oder mehreren Zeichen zu zitieren, (dh 'xx..'
, "xx.."
) oder durch einen individuellen Charakter mit einem Back-Slash Vorfixierung (dh \x
). (Es ist etwas komplizierter, da die Anführungszeichen auch zitiert werden müssen und weil doppelte Anführungszeichen nicht alles zitieren, aber diese Vereinfachung reicht vorerst aus.)
Verwechseln Sie Bash-Zitate nicht mit der Idee, eine Textfolge wie in anderen Sprachen zu zitieren. Was sich zwischen Anführungszeichen in Bash befindet, sind keine Zeichenfolgen, sondern Abschnitte der Eingabezeile, bei denen Metazeichen maskiert sind, um Token nicht zu begrenzen.
Beachten Sie, dass es einen wichtigen Unterschied zwischen '
und gibt "
, aber das ist für einen anderen Tag.
Die verbleibenden nicht entkappten Metazeichen werden dann zu Token-Trennzeichen.
Beispielsweise,
$ echo "x"'y'\g
xyg
$ echo "<"'|'\>
<|>
$ echo x\; echo y
x; echo y
Im ersten Beispiel gibt es zwei Token, die von einem Leerzeichenbegrenzer erzeugt werden: echo
und xyz
.
Ebenso im 2. Beispiel.
Im dritten Beispiel wird das Semikolon entkam, so gibt es 4 - Token von einem Leerzeichen Trennzeichen erzeugt, echo
, x;
, echo
, und y
. Das erste Token wird dann als Befehl ausgeführt und verwendet die nächsten drei Token als Eingabe. Beachten Sie, dass der 2. echo
nicht ausgeführt wird.
Die wichtige Sache zu erinnern , dass die bash erste Blicke zu entkommen Zeichen sind ( '
, "
, und \
) und sucht dann nach unescaped Meta-Zeichenbegrenzern, in dieser Reihenfolge.
Wenn nicht, dienen diese 10 Sonderzeichen als token
Begrenzer. Einige von ihnen haben auch eine zusätzliche Bedeutung, aber in erster Linie sind sie Token-Begrenzer.
Was grep erwartet
In dem obigen Beispiel grep diese Token benötigt, grep
, string
, filename
.
Der erste Versuch der Frage war:
$ grep (then | there) xx
In diesem Fall (
, )
und |
sind unescaped Meta - Zeichen und so dazu dienen , den Eingang in diese Token aufgeteilt: grep
, (
, then
, |
, there
, )
, und x.x
. grep sehen will grep
, then|there
und x.x
.
Der zweite Versuch der Frage war:
grep "(then | there)" xx
Diese tokenizes zu grep
, (then|there)
, x.x
. Sie können dies sehen, wenn Sie grep gegen echo austauschen:
echo "(dann | dort)" xx
(dann | dort) xx