Was macht \? meine in einem regulären Ausdruck?

16

Mit dem folgenden Befehl wird nach einer 7-stelligen Telefonnummer gesucht:

grep "[[:digit:]]\{3\}[ -]\?[[:digit:]]\{4\}" file

Was bedeutet \?stehen?

user5997
quelle

Antworten:

21

Es ist wie ?in vielen anderen Modulen für reguläre Ausdrücke und bedeutet "Keine Übereinstimmung oder eine der vorhergehenden Übereinstimmungen".

In Ihrem Beispiel wird das auf \?das angewendet [ -], was bedeutet, dass versucht wird, ein Leerzeichen oder ein Minuszeichen zuzuordnen, das Leerzeichen oder Minuszeichen jedoch optional ist.

So wird eines dieser übereinstimmen:

555 1234
555-1234
5551234

Der Grund , warum es so geschrieben , \?anstatt ?ist für die Abwärtskompatibilität.

Die ursprüngliche Version von grepverwendete eine andere Art von regulären Ausdrücken, die als "reguläre Basisausdrücke" bezeichnet wurde und ?nur ein wörtliches Fragezeichen bedeutete.

Damit GNU grep die Null- oder Eins-Funktionalität haben konnte, fügten sie diese hinzu, mussten jedoch die \?Syntax verwenden, damit die verwendeten Skripte ?weiterhin wie erwartet funktionierten.

Beachten Sie, dass grep über eine -EOption verfügt, die die Verwendung des allgemeineren Typs regulärer Ausdrücke ermöglicht, der als "erweiterte reguläre Ausdrücke" bezeichnet wird.

man 1 grep:

   -E, --extended-regexp
          Interpret PATTERN as an extended regular expression
          (ERE, see below).  (-E is specified by POSIX.)

   -G, --basic-regexp
          Interpret PATTERN as a basic regular expression (BRE, see below).
          This is the default.

...

Repetition
    A regular expression may be followed by one of several repetition operators:
    ?      The preceding item is optional and matched at most once.

...

    grep understands three different versions of regular expression syntax:
    “basic,” “extended” and “perl.”

...

Basic vs Extended Regular Expressions
    In basic regular expressions the meta-characters ?, +, {, |, (, and )
    lose their special meaning; instead use the backslashed versions
    \?, \+, \{, \|, \(, and \).

Weitere Infos:

Mikel
quelle
Der egrepBefehl ist äquivalent zu grep -E. Bei anderen Versionen als GNU grep wird grepdie -EOption möglicherweise akzeptiert oder nicht , und es handelt sich egrepmöglicherweise um ein separates Programm.
Keith Thompson
@KeithThompson, grep -Eist der offizielle POSIX-Weg. egrepwurde in susv2 (1997) veraltet und in susv3 (2001) aus den POSIX- und Unix-Spezifikationen entfernt.
Stéphane Chazelas
1
\?ist allerdings ein GNUism.
Stéphane Chazelas
8

Leider unterscheidet sich die genaue Syntax regulärer Ausdrücke zwischen verschiedenen Programmen geringfügig: reguläre Ausdrücke für grep sind nicht identisch mit regulären Ausdrücken für sed, die nicht identisch mit regulären Ausdrücken für Emacs sind, die nicht identisch mit regulären Ausdrücken für C ++ sind auf. Erschwerend kommt hinzu, dass sogar ein "Standard" -Tool wie grep zwischen verschiedenen Unix-ähnlichen Betriebssystemen leicht variieren kann.

In einer Regex haben einige Zeichen eine spezielle Bedeutung (wie die eckigen Klammern in Ihrem Beispiel) und kehren zu ihrer normalen Bedeutung als wörtliche Zeichen zurück, wenn Sie sie durch einen umgekehrten Schrägstrich "entkommen" (so würde es eine wörtliche Klammer sein) geschrieben als \ [). Andere arbeiten umgekehrt und erhalten nur dann eine besondere Bedeutung, wenn sie maskiert werden (z. B. n ist nur ein Buchstabe, aber \ n ist ein Zeilenvorschub). Und diese können wiederum zwischen Regex-Implementierungen variieren.

In den meisten Regex-Implementierungen bedeutet ein Fragezeichen, dass das vorherige Element optional ist, während ein maskiertes Fragezeichen (\?) Ein wörtliches Fragezeichen ist. In einigen Dialekten ist es jedoch umgekehrt. Ihr Beispiel könnte so oder so Sinn machen, aber ich vermute, Sie haben einen der Dialekte, in denen? ist ein wörtliches und \? ist das optionale Symbol. Ihre Regex bedeutet also wahrscheinlich "drei Ziffern, optional gefolgt von einem Leerzeichen oder Bindestrich, gefolgt von vier Ziffern".

(Ein weiterer Hinweis kann in Konstrukten wie \ {3 \} gesehen werden, die eindeutig "genau 3 des vorherigen Elements" bedeuten sollen. In den meisten Regex-Dialekten wäre dies {3} und \ {wäre eine wörtliche Klammer .)

Ross Smith
quelle
6

Dies ist eine kurze Zusammenfassung der Informationen, die bereits in den anderen Antworten enthalten sind.

In grep, ?entspricht einem wörtlichen Fragezeichen und \?bezeichnet null oder ein Vorkommen dessen, was davor steht. Im Beispiel in Ihrer Frage [ -]\?entspricht dies entweder einem Leerzeichen oder einem Bindestrich oder gar nichts.

In egrepoder grep -Eist es umgekehrt; \?Entspricht einem wörtlichen Fragezeichen und gibt ?null oder ein Vorkommen an.

Dies gilt für GNU grep; Die Details für Nicht-GNU-grep-Implementierungen können geringfügig abweichen. Insbesondere grepund egrephistorisch gesehen waren es zwei getrennte Programme, und ich glaube nicht, dass alte grepdie -EOption hatten. POSIX gibt an grep -E, aber (ich war überrascht zu entdecken) nicht zu erwähnen egrep.

Keith Thompson
quelle