Warum haben einige Regex-Befehle entgegengesetzte Interpretationen von '\' mit verschiedenen Zeichen?

10

Nehmen Sie zum Beispiel diesen Befehl:

find . -regex ".*\.\(cpp\|h\)"

Dadurch werden alle .h- und .cpp-Dateien in Ihrem Verzeichnis gefunden. Das Punktzeichen '.' in regulären Ausdrücken bedeutet normalerweise "jedes Zeichen". Damit es nur einem tatsächlichen Zeitraum entspricht, müssen Sie es mit dem Backslash-Zeichen '\' maskieren.

In diesem Fall müssen Sie ein Zeichen mit einer besonderen Bedeutung maskieren, um das tatsächliche Zeichen zu erhalten, das es darstellt.

Nehmen Sie nun die Klammern und den Balken "oder" als Zeichen '(', ')' bzw. '|'. Diese haben auch spezielle Bedeutungen, die zum Gruppieren regulärer Ausdrücke verwendet werden. Um die besondere Bedeutung zu erhalten, müssen die Zeichen jedoch mit dem Backslash maskiert werden! Ohne den Backslash haben die Zeichen die Bedeutung des tatsächlichen Zeichens, das sie darstellen.

Warum ist der '.' anders behandelt als '(', ')' und '|'?

Cory Klein
quelle

Antworten:

12

Die Antwort ist wirklich "nur weil". Es gibt eine ganze Reihe verschiedener Syntaxen für reguläre Ausdrücke, und obwohl sie ein ähnliches Erscheinungsbild haben und die Grundlagen normalerweise gleich sind, unterscheiden sie sich in den Einzelheiten.

In der Vergangenheit hatte jedes Tool seine eigene neue Implementierung, die das tat, was der Autor für am besten hielt. Es gibt ein Gleichgewicht zwischen der Besonderheit von Charakteren mit und ohne Flucht - zu viele Charaktere, die "von Natur aus etwas Besonderes" sind, und Sie müssen ihnen die ganze Zeit entkommen, nur um sie zu finden. oder umgekehrt, Sie benötigen am Ende eine Reihe von Escapezeichen, um die allgemeine Regex-Syntax wie () Gruppierung zu verwenden. Und jeder, der ein Programm schrieb, entschied, wie es zu tun war, basierend auf den Bedürfnissen, mit denen sein Programm übereinstimmte, auf dem, was er für den richtigen Ansatz hielt, und auf der Mondphase.

Es wird versucht, POSIX zu standardisieren, wobei " grundlegende reguläre Ausdrücke " und " erweiterte reguläre Ausdrücke " definiert werden. Erstaunlicherweise arbeiten diese in Bezug auf \- manchmal , aber nicht mit perfekter Konsistenz - rückwärts voneinander .

Perl-reguläre Ausdrücke sind aus zwei Gründen zu einem weiteren Defacto-Standard geworden: Erstens sind sie sehr flexibel und leistungsstark, und zweitens sind sie tatsächlich ziemlich vernünftig , mit Konventionen wie "\ entgeht immer einem nicht-alphanumerischen Zeichen".

GNU Find verfügt über eine -regextypeOption, mit der Sie die verwendete Syntax für reguläre Ausdrücke ändern können. Leider ist "Perl" keine Option, zumindest in der Version von find, die ich habe. (Die Standardeinstellung ist, nicht überraschend von GNU, "emacs", und diese Syntax ist hier dokumentiert .)

mattdm
quelle