Warum muss ich Regex-Zeichen in sed maskieren, um als Regex-Zeichen interpretiert zu werden?

11

Es scheint zB,
cat sed_data.txt | sed 's/\b[0-9]\{3\}\b/NUMBER/g'
dass ich Zeichen entkommen muss , um einen regulären Ausdruck zu bilden. In diesem Fall musste ich Zahnspangen entkommen, um mehrmals interpretiert zu werden.
Warum? Ich hatte erwartet, dass alles ein Regex-Charakter sein würde, wenn es nicht entkommen würde. Dh das Gegenteil.

Jim
quelle
Es gab einen Beitrag über die Suche in Vim, der diese Frage etwas abdeckt. Die Kurzversion lautet
Drav Sloan
@DravSloan: Ich bin nicht sicher, ob es dasselbe ist. In Vim suchen Sie standardmäßig nach Text und müssen entkommen, um nach Regex zu suchen. In diesem Fall erwartet das Format jedoch s/regex//gbereits einen Regex und ich würde erwarten, dass es Text ist, der benötigt wird zu entkommen
Jim

Antworten:

14

Dies liegt daran , sedAnwendungen POSIX BREs (Grund Regular Expressions) in Bezug auf die EREs gegen (Reguläre Ausdrücke Extended) Sie wahrscheinlich von Perl oder Freunden verwendet.

Von der sed(1)Manpage:

REGULAR EXPRESSIONS
       POSIX.2 BREs should be supported, but they aren't completely because of
       performance problems.  The \n sequence in a regular expression  matches
       the newline character, and similarly for \a, \t, and other sequences.

Relevantes Zitat aus dem obigen Link:

Das Basic Regular Expressions- oder BRE-Aroma standardisiert ein Flair, das dem des traditionellen UNIX-Befehls grep ähnelt. Dies ist so ziemlich das älteste Aroma mit regulären Ausdrücken, das heute noch verwendet wird. Eine Sache, die dieses Aroma auszeichnet, ist, dass die meisten Metazeichen einen Backslash benötigen, um dem Metazeichen seinen Geschmack zu verleihen. Die meisten anderen Geschmacksrichtungen, einschließlich POSIX ERE, verwenden einen Backslash, um die Bedeutung von Metazeichen zu unterdrücken.

Wörtlich zitiert aus Craig Sanders 'Kommentar :

Beachten Sie, dass Sie sed zumindest in GNU sed anweisen können, erweiterte reguläre Ausdrücke mit der erweiterten Befehlszeilenoption -r oder --regexp zu verwenden. Dies ist nützlich, wenn Sie vermeiden möchten, Ihr sed-Skript durch übermäßiges Escape zu hässlich zu machen.

Joseph R.
quelle
1
Beachten Sie, dass Sie sed zumindest in GNU sed anweisen können, erweiterte reguläre Ausdrücke mit der Befehlszeilenoption -roder zu verwenden --regexp-extended. Dies ist nützlich, wenn Sie vermeiden möchten, Ihr sed-Skript durch übermäßiges Escape zu hässlich zu machen.
Cas
@CraigSanders Danke dafür. Zur Antwort hinzugefügt.
Joseph R.
@CraigSanders, andere sedImplementierungen (wenn sie EREs unterstützen, meistens BSDs) verwenden dies eher -E(was viel sinnvoller ist, da dies die gleiche Option ist wie für grep. Warum GNU sedgewählt hat, -rist mir ein Rätsel).
Stéphane Chazelas
Ja, auch mir ein Rätsel. Es wäre sinnvoller, -E zu verwenden. und fügen Sie dann -F, -G und -P hinzu, um GNU grep zu entsprechen. IMO Gawk würde auch von den gleichen RE-Argumenten profitieren ... oder zumindest -P.
Cas
12

Das hat historische Gründe.

Regexp wurde edAnfang der 70er Jahre erstmals in Unix im Dienstprogramm eingeführt . Obwohl edstützte sich auf qedderen Umsetzung durch die gleichen Autoren komplexere regexp verstanden, edverstanden nur ^, $, [...], ., *und \alle oben zu entkommen.

Als nun die Notwendigkeit bestand, mehr Operatoren zu haben, musste ein Weg gefunden werden, diese einzuführen, ohne die Abwärtskompatibilität zu beeinträchtigen. Wenn ein Skript den s edBefehl verwendet s/foo() {/foo (var) {/g, um alle Instanzen von foo() {durch zu ersetzen, foo(var) { und Sie einen (oder {-Operator eingeführt haben, würde dieses Skript beschädigt.

Allerdings würde kein Skript ausreichen s/foo\(\) {/foo\(var\) {/, da dies dasselbe ist s/foo() {/foo(var) {/und es keinen Grund gab, zu entkommen, (da dies kein RE-Operator war. Die Einführung eines neuen \(oder \{Operators beeinträchtigt also nicht die Abwärtskompatibilität, da es sehr unwahrscheinlich ist, dass ein vorhandenes Skript mit der älteren Syntax beschädigt wird.

So wurde es gemacht. Später \(...\)wurde zunächst nur für den s edBefehl hinzugefügt , Dinge wie s/foo\(.\)/\1bar/und später als grep '\(.\)\1'(aber noch nicht wie \(xx\)*) zu tun .

In UnixV7 (1979, also fast ein Jahrzehnt später) wurde eine neue Form von regulären Ausdrücken in den neuen egrepund awkDienstprogrammen hinzugefügt, die als erweiterter regulärer Ausdruck bezeichnet werden (da es sich um neue Tools handelt, kann keine Abwärtskompatibilität unterbrochen werden). Endlich, sofern sie mit der Funktionalität in dem Ken Thompson altem qed(Wechsel Operator |, Gruppierung (..)*) und einige Operatoren hinzugefügt wie +und ?(aber nicht über das backref Merkmal der grundlegenden regulären Ausdrücken).

Später fügten die BSDs \<und \>(sowohl zu BRE als auch zu ERE) hinzu, und SysV fügte hinzu \{und nur \}zu BREs.

Es ist nicht viel später als {und }wurden zu ERE hinzugefügt, durch solche brechende Abwärtskompatibilität. Nicht jeder hat es hinzugefügt. Beispielsweise wurde GNU awkbis Version 4.0.0 (2011) nur unterstützt, {wenn es in den POSIX-Konformitätsmodus versetzt wurde.

wenn GNU grepin den frühen 90er Jahren geschrieben wurde, hat es alle guten Sachen von beiden BSD und SysV (wie \<, {) und anstelle von zwei getrennten regexp - Syntax und Motor für BRE und ERE, die gleichen Operatoren in beiden implementiert werden nur die BRE Pendants von (, ?, {, +mit einem umgekehrten Schrägstrich werden müssen voran (kompatibel sein mit anderen Implementierungen BRE). Aus diesem Grund können Sie dies .\+in GNU tun grep(obwohl dies nicht POSIX ist oder von anderen Implementierungen unterstützt wird) und Sie können dies (.)\1in GNU tun egrep(obwohl dies nicht POSIX ist oder von vielen anderen Implementierungen einschließlich GNU unterstützt wird awk).

Das Hinzufügen von \xOperatoren ist nicht die einzige Möglichkeit, weitere Operatoren abwärtskompatibel hinzuzufügen. Zum Beispiel perlverwendet (?...). Das ist immer noch abwärtskompatibel mit EREs, da (?=...)dies in EREs nicht gültig ist .*?. vimfür ähnliche Betreiber hat es anders gemacht durch Einführung \@=oder .\{-}zum Beispiel.

Stéphane Chazelas
quelle