Was ist der Unterschied zwischen a[bc]d
und a{b,c}d
? Warum nutzen Menschen, a{b,c}d
wenn es sie schon gibt a[bc]d
?
ls
versuchen und Sie immer nur einzelne Zeichen versuchen, scheinen sie gleich zu funktionieren.
Was ist der Unterschied zwischen a[bc]d
und a{b,c}d
? Warum nutzen Menschen, a{b,c}d
wenn es sie schon gibt a[bc]d
?
ls
versuchen und Sie immer nur einzelne Zeichen versuchen, scheinen sie gleich zu funktionieren.
Antworten:
Die beiden sind sehr unterschiedlich.
a[bc]d
ist ein Dateinamenmuster (in anderen Shells als fish
). Es wird auf die beiden Dateinamen erweitert abd
und acd
ob dies die Namen der im aktuellen Verzeichnis vorhandenen Dateien sind.
Der [...]
Teil ist ein Ausdruck in eckigen Klammern, der mit einem der aufgelisteten Zeichen übereinstimmt (oder Elemente sortiert, wenn Bereiche enthalten sind). Um das Muster abzugleichen, muss a[bc]d
das Zeichen zwischen den Zeichenfolgen a
und d
in einem Dateinamen entweder a b
oder a sein c
.
Wenn es abd
existiert, aber acd
nicht, dann würde es nur expandieren abd
und umgekehrt.
Wenn weder abd
, noch acd
vorhanden ist , in Abhängigkeit von der Schale und den Optionen, würde es einen Fehler (Original Unix auslösen sh
, (t)csh
, zsh
, fish
, bash -O failglob
) und möglicherweise den Shell verlassen, oder lassen Sie das Muster unexpanded¹ (Bourne-like und rc
-artigen Schalen) oder erweitern , um nichts ( bash/zsh/yash -o nullglob
einige ältere Versionen von fish
Original-Unix sh
und (t)csh
wenn es andere übereinstimmende Globs im selben Befehl gibt).
a{b,c}d
ist eine Klammererweiterung (in Schalen, die diese unterstützen). Es wird auf die beiden Saiten abd
und erweitert acd
.
Der {...}
Teil ist eine durch Kommas getrennte Menge von Zeichenfolgen (in diesem Beispiel; in einigen Shell-Fällen kann es sich auch um einen Bereich wie a..k
oder 20..25
oder einen fortgeschritteneren wie 00..20..2
oder handeln 0..20..2%02d
). Die Erweiterung wird berechnet, indem jede dieser Zeichenfolgen mit der Flanke kombiniert wird Streicher a
und d
. Diese Zeichenfolgen können länger als ein einzelnes Zeichen sein und können auch selbst Klammererweiterungen sein.
Die Erweiterung erfolgt unabhängig davon, ob diese Zeichenfolgen vorhandenen Dateinamen entsprechen oder nicht.
Wenn Sie Zeichenfolgen erstellen, verwenden Sie eine geschweifte Klammer. Wenn Sie mit Dateinamen übereinstimmen, verwenden Sie ein Dateinamenmuster.
¹ In diesem speziellen Fall kann es vorkommen, a[bc]d
dass es sich um den Namen einer vorhandenen Datei handelt, weshalb es möglicherweise gefährlich ist, Dinge wie diese rm -f ./*.[ch]
in Shells zu verwenden, und dies rm -f ./*.{c,h}
ist weniger problematisch.
a{b,c}d
die b
und c
-Teile keine einzelnen Buchstaben sein müssen. zB ex{ten,ci}sion
. Wobei ex[tenci]sion
oder was auch immer nur mit einem dieser Buchstaben übereinstimmt .
a[bc]d
ist eine Mustererkennung und Teil des POSIX-Standards. In POSIX wird dies als "Musterklammerausdruck" eingeführt. Dies ist in Abschnitt 2.13 des Handbuchs dokumentiert
Ohne Anführungszeichen und außerhalb eines Klammerausdrucks haben die folgenden drei Zeichen in der Spezifikation von Mustern eine besondere Bedeutung:
?
Ein Fragezeichen ist ein Muster, das mit einem beliebigen Zeichen übereinstimmt.
*Ein Stern ist ein Muster, das mit mehreren Zeichen übereinstimmen soll, wie in Muster, die mit mehreren Zeichen übereinstimmen beschrieben.
[Die offene Klammer soll einen Musterklammerausdruck einführen.
In Abschnitt 2.13.3 wird auch etwas erwähnt, das sich anders verhält als man es von regulären Ausdrücken erwartet, wenn es für die Dateinamenerweiterung verwendet wird (Hervorhebung von mir).
Die Regeln, die bisher in Muster, die mit einem einzelnen Zeichen übereinstimmen, und Muster, die mit mehreren Zeichen übereinstimmen, beschrieben wurden, werden durch die folgenden Regeln qualifiziert, die gelten, wenn die Mustervergleichsnotation für die Dateinamenerweiterung verwendet wird:
Das Schrägstrichzeichen in einem Pfadnamen muss explizit mit einem oder mehreren Schrägstrichen im Muster verglichen werden. Es darf weder mit einem Sternchen oder einem Fragezeichen als Sonderzeichen noch mit einem Klammerausdruck übereinstimmen. Schrägstriche im Muster sind vor Klammerausdrücken zu kennzeichnen. Daher kann ein Schrägstrich nicht in einem Musterklammerausdruck enthalten sein, der für die Dateinamenerweiterung verwendet wird. Wird ein Schrägstrich nach einem offenen eckigen Klammerzeichen gefunden, bevor eine entsprechende schließende eckige Klammer gefunden wird, wird die offene Klammer als gewöhnliches Zeichen behandelt. Beispielsweise
"a[b/c]d"
stimmt das Muster nicht mit solchen Pfadnamen wieabd
oder übereina/d
. Es stimmt nur mit einem Pfadnamen von wörtlich übereina[b/c]d
.
a{b,c}d
ist eine Klammererweiterung , sie ist nicht in der Spezifikation von POSIX enthalten. Hier ist der entsprechende Teil aus dem Bash- Handbuch (Hervorhebung von mir):
Die Klammererweiterung ist ein Mechanismus, mit dem beliebige Zeichenfolgen generiert werden können. Dieser Mechanismus ähnelt der Dateinamenerweiterung (siehe Dateinamenerweiterung), die generierten Dateinamen müssen jedoch nicht vorhanden sein . Muster, die in geschweifte Klammern eingeschlossen werden sollen, haben die Form einer optionalen Präambel, gefolgt von einer Reihe von durch Kommas getrennten Zeichenfolgen oder einem Sequenzausdruck zwischen zwei geschweiften Klammern, gefolgt von einem optionalen Nachskript. Die Präambel wird jeder in geschweiften Klammern enthaltenen Zeichenfolge vorangestellt, und das Nachskript wird dann an jede resultierende Zeichenfolge angehängt und von links nach rechts erweitert.
Laut dem Kommentar von @mosvy ist dies zuerst von aufgetaucht, csh
aber das Verhalten in bash
unterscheidet sich von csh
und von anderen Shells. Diese Art der Strebendehnung ist auch in vorhanden glob(3)
.
Es gibt eine andere Art der Klammererweiterung {a..z}
, die erst nach bash
3.0 erschien, und in bash
4.0 wurden weitere hinzugefügt .
Führen Sie in einer Shell, in der das Globbing aktiviert ist, in einem leeren Ordner das folgende Ergebnis aus
$ echo a[bc]d
a[bc]d
$ echo a{b,c}d
abd acd
Wenn Sie sich in einer interaktiven Shell befinden und beide zutreffen, haben Sie als Antwort auf den Kommentar von @ Jesse_b a[bc]d
weniger Probleme bei der Eingabe. Zum Beispiel grep pattern [ab][12].txt
.
csh
, lange bevor bash
. Es ist auch in der Bibliotheksfunktion glob (3) enthalten. Der Unterschied besteht darin, dass bash
es vor anderen Erweiterungen ausgeführt wird: Es a=A; ab=A/B; ac=A/C; echo $a{b,c}
funktioniert in bash anders als in jeder anderen Shell.
command a[bc]d
?