Gibt es einen historischen Grund, warum Bash "Globbing" und reguläre Ausdrücke nicht identisch sind? Ich glaube zum Beispiel, dass in Bash [1-2]*
alles übereinstimmt, was mit einer 1 oder einer 2 beginnt, gefolgt von etwas anderem, während ein regulärer Ausdruck [1-2]*
nur einer Folge von 1s und 2s entspricht. Mein Bash-Scripting und REGEX foo sind beide ziemlich schwach und ich stoße regelmäßig auf Probleme im Zusammenhang mit diesen Unterschieden, die mich neugierig machten, warum sie unterschiedlich sind.
shell
regular-expression
wildcards
history
StrongBad
quelle
quelle
rm -- ^[^.].*\.txt$
stattrm -- *.txt
?find . -regex ".*\.txt$" | xargs rm --
oderrename
Umbenennen von Dateien (dies giltsed
für Dateinamen) darauf, dass einige Systeme einen anderen habenrename
.^[^.].*\.txt$
war es, das Ignorieren von Punktdateien zu berücksichtigen. Beachten Sie, dass das-regex
ist eine GNU - Erweiterungen, einige Shells wie ksh93 oder zsh kann regexps in ihren Kleckse (zum Beispiel versuchen: inkorporierenksh93 -c 'echo ~(E:^[^.].*\.txt$)'
)Antworten:
bash
wurde ursprünglich in den späten 80ern als Teilklonksh
mit einigen interaktiven Funktionen von csh / tcsh entworfen.Die Ursprünge des Globbing müssen in den früheren Muscheln liegen, auf denen es aufbaut.
ksh
selbst ist eine Erweiterung der Bourne-Shell. Die Bourne-Shell selbst (erstmals 1979 in Unix V7 veröffentlicht) war eine saubere Implementierung von Grund auf neu, weicht jedoch nicht vollständig von der Thompson-Shell (der Shell von V1 -> V6) ab und enthält Funktionen der Mashey-Shell.Insbesondere wurden Befehlsargumente immer noch durch Leerzeichen getrennt,
|
war jetzt der neue Pipe-Operator,^
wurde aber weiterhin als Alternative unterstützt (und erklärt auch, warum Sie dies tun[!a-z]
und nicht[^a-z]
),$1
war immer noch das erste Argument für ein Skript und Backslash war immer noch das Escape-Zeichen . So viele der regulären Ausdrucksoperatoren (^\|$
) haben in der Shell eine eigene Bedeutung.Die Thompson-Shell stützte sich beim Globbing auf ein externes Dienstprogramm. Wenn
sh
nicht notiert gefunden*
,[
oder?
s in dem Befehl, würde es den Befehl durchlaufenglob
.würde am Ende glob laufen als:
und glob würde am Ende
rm
mit der Liste der Dateien ausgeführt, die diesem Muster entsprechen.würde laufen
glob
als:Das
*
Obige wurde zitiert, indem das 8. Bit für dieses Zeichen gesetzt wurde, um zu verhindernglob
, dass es als Platzhalter behandelt wird.glob
würde dann dieses Bit vor dem Aufruf entfernengrep
.Um das Äquivalent mit regulären Ausdrücken zu machen, wäre das gewesen:
Oder:
Punktdateien ausschließen.
Die Notwendigkeit, den Operatoren zu entkommen, da sie als Shell-Sonderzeichen
.
fungieren , und die Tatsache, dass in Dateinamen häufig ein regulärer Ausdrucksoperator verwendet wird, macht es für Anfänger nicht sehr angemessen, Dateinamen abzugleichen und kompliziert. In den meisten Fällen benötigen Sie lediglich Platzhalter , die entweder ein (?
) oder eine beliebige Anzahl (*
) von Zeichen ersetzen können .Jetzt haben verschiedene Shells verschiedene Globbing-Operatoren hinzugefügt. Heutzutage sind die ksh- und zsh-Globs (und in gewissem Maße
bash -O extglob
eine Teilmenge von ksh-Globs) funktional äquivalent zu regulären Ausdrücken mit einer Syntax, deren Verwendung mit Dateinamen und der aktuellen Shell-Syntax weniger umständlich ist. Inzsh
(mit Extendedglob-Erweiterung) können Sie beispielsweise Folgendes tun:wenn Sie (unwahrscheinlich) mit Dateinamen übereinstimmen möchten, die aus Sequenzen von
a
gefolgt von bestehen.txt
. Einfacher alsecho (^a*\.txt$)
(hier die Verwendung von geschweiften Klammern, um die Regex-Operatoren von den Shell-Operatoren zu isolieren, die eine Möglichkeit gewesen sein könnten, wie Shells damit umgehen könnten).Für mpg-Dateien (ohne Berücksichtigung der Groß- und Kleinschreibung), deren Basisname foo, bar oder eine Dezimalzahl von 1 bis 20 ist ...
ksh93
Jetzt können auch reguläre Ausdrücke (einfach, erweitert, perlartig oder "erweitert") in die Globs integriert werden (obwohl dies ziemlich fehlerhaft ist) und es wird sogar ein Tool zum Konvertieren zwischen glob und regulärem Ausdruck (printf %R
,printf %P
) bereitgestellt :zu Spiel (nicht verborgen) txt - Dateien mit E regulären Ausdrücken Xtended, Case- i nsensitively.
quelle
~(opt:pat)
keine der aktivierten Optionen verwenden. Vielleichtprint -r -- ~(Ei).*\.txt$
. Das Einfügen des Musters scheint nur nützlich zu sein, um zu vermeiden, dass eine Option für einen Teil eines Musters ein- und ausgeschaltet werden muss. Seltsamerweise können Sie jedoch mehrere Mustersprachen innerhalb eines Globus mischen und anpassen.~(Ki)*.~(E)txt$
ist gleichwertig. (Am Ende wird alles nur in Regex konvertiert und intern an die Regex-Engine von libast übergeben.)~(Ei:.*\.txt)
funktioniert für mich auch mit 15 Jahre alten Versionen wie ksh93 o +.~(E)x
und~(E:x)
ist, dass Letzteres verankert ist (stimmtx
nur überein, während Ersteres mit etwas übereinstimmtx
, das etwas enthält ), was möglicherweise die Art von Problem ist, auf die Sie gestoßen sind (~(-lr)~(E:x)
zum Entfernen der Verankerung~(E-lr:x)
nicht geeignet ). Auf jeden Fall stimme ich zu, dass es selbst in der neuesten Version ziemlich fehlerhaft ist.Reguläre Sprachen wurden 1956 von Kleene eingeführt . Das wegweisende Papier hatte nicht die vollständige moderne Notation für reguläre Ausdrücke, aber es führte den „Kleen-Stern“ ein:
A*
„beliebig viele Wiederholungen vonA
“. Im nächsten Jahrzehnt entstanden einige mehr oder weniger Standardnotationen, insbesondere.
für ein beliebiges Zeichen und um?
zu bedeuten, dass das vorherige Zeichen optional ist.Die Globbing-Notation von Bash stammt aus dem
glob
Befehl , der bereits 1971 in Unix v1 eingeführt wurde. Zu dieser Zeit wurde das Globbing von einem separaten Programm ausgeführt. es wurde später in die Schale bewegt. Der früheglob
Befehl muss?
"ein beliebiges Zeichen" und*
"eine beliebige Folge von Zeichen" bedeuten. Ich weiß nicht, warum die Charaktere ausgewählt wurden;?
ist ziemlich intuitiv und wurde*
möglicherweise von dem in regulären Ausdrücken inspiriert.Globbing sollte nicht so allgemein sein wie reguläre Ausdrücke, und reguläre Ausdrücke waren zu dieser Zeit nicht sehr verbreitet, so dass es keinen Aufruf gab, die Konzepte zu vereinheitlichen. Von Anfang an gab es syntaktische Inkompatibilitäten mit
?
,.
und*
was bedeutet , verschiedene Dinge in Dateinamen Muster und in regulären Ausdrücken.Moderne Muscheln wie Bash erweitern die Glob-Muster, aber es war eine schrittweise Entwicklung, die die Abwärtskompatibilität aufrechterhielt. Ksh88 (die 1988er Version der Korn-Shell ) führte eine erweiterte Syntax für Shell-Muster ein, die nicht die gleiche Syntax wie übliche reguläre Ausdrücke haben konnte, aber stark davon inspiriert war:
*(PATTERN)
eine beliebige Anzahl von Wiederholungen vonPATTERN
, oder " oder "@(PATTERN1|PATTERN2)
zu bedeuten , etc.PATTERN1
PATTERN2
Moderne Versionen von bash (seit 2.02) unterstützen die erweiterten Muster von ksh88, wenn Sie dies
shopt -s extglob
zuerst tun .quelle
extglob
Option wurden irgendwann um 1998 in Bash 2.02 eingeführt. Zsh wurdeksh_glob
ungefähr zur gleichen Zeit in der 3.1-Serie erworben . Zsh hat viele eigene Globbing-Erweiterungen (einige erfordern dieextended_glob
Option).bash
Gegensatz zuksh
extglob nicht POSIX-konform macht, da es in Variablen nicht deaktiviert ist. Inksh
,var='@(*)'; echo $var
dehnt sich im aktuellen Verzeichnis , um alle Dateinamen , die mit Start@(
und Ende in)
POSIX während erfordert inbash -O extglob
es die Dateien auf alle erweitert. (Dennoch kann man Bash-Verhalten hier für sinnvoller halten (und das ksh-Verhalten ist ziemlich schmerzhaft, wenn Sie Muster in Variablen haben möchten)). Diese Glob-Syntax ist deshalb so umständlich (POSIX / Bourne-Kompatibilität). Vergleichen Sie mit zsh Extended Globs.Historischer Grund: JA. Referenz:
http://en.wikipedia.org/wiki/Glob_(programming)#Origin
Um die Divergenz zu veranschaulichen, hier ein gutes und einfaches Beispiel:
a*
a
und dann was auch immer (a, ab, abca ...)a
(a, aa, aaa ...)Ich würde gerne zustimmen, dass diese Bedeutungsdiskrepanz für neue Benutzer sehr verwirrend ist.
Globbing ist für Neulinge vielleicht leichter zu verstehen, aber es ist auch ein weniger leistungsfähiges Konstrukt.
quelle