Regular Expression/Suchmuster: Unterschied zwischen den Versionen

Aus Foxwiki
Die Seite wurde neu angelegt: „== Suchmuster == === Sonderzeichen in Suchmustern === ; Sonderzeichen in Suchmustern {| class="wikitable sortable" |- | | <tt>'''.'''</tt> | | Steht für ein beliebiges *einzelnes* Zeichen, mit Ausnahme des Zeilenendezeichens |- | | <tt>'''*'''</tt> | | * Steht für eine beliebige (auch leere) Menge des einzelnen Zeichens vor dem Sternchen. * Das vorangehende Zeichen kann auch ein regulärer Ausdruck sein. * Beispielsweise steht .* für eine beliebige Anz…“
 
Keine Bearbeitungszusammenfassung
Zeile 418: Zeile 418:


In einigen Programmen kann mithilfe des sogenannten ''Single-Line''-Modifiers <tt>s</tt> (zum Beispiel in <tt>/foo.bar/s</tt>) ebendies erreicht werden.
In einigen Programmen kann mithilfe des sogenannten ''Single-Line''-Modifiers <tt>s</tt> (zum Beispiel in <tt>/foo.bar/s</tt>) ebendies erreicht werden.
[[Kategorie:RegEx]]

Version vom 14. Oktober 2024, 11:52 Uhr

Suchmuster

Sonderzeichen in Suchmustern

Sonderzeichen in Suchmustern
. Steht für ein beliebiges *einzelnes* Zeichen, mit Ausnahme des Zeilenendezeichens
* * Steht für eine beliebige (auch leere) Menge des einzelnen Zeichens vor dem Sternchen.
  • Das vorangehende Zeichen kann auch ein regulärer Ausdruck sein.
  • Beispielsweise steht .* für eine beliebige Anzahl eines beliebigen Zeichens
^ Übereinstimmung, wenn der folgende Ausdruck am Zeilenanfang steht
$ Übereinstimmung, wenn der vorhergehende Azusdruck am Zeilenende steht
\ Schaltet die Sonderbedeutung des nachfolgenden Zeichens ab
[ ] * Steht für *ein* beliebiges Zeichen aus der eingeklammerten Gruppe.
  • Mit dem Bindestrich kann man einen Bereich aufeinanderfolgender Zeichen auswählen ([a-e]).
  • Ein Zirkumflex (^) wirkt als Umkehrung: [^a-z] erfaßt alle Zeichen, die keine Kleinbuchstaben sind.
  • Ein Bindestrich oder eine schließende eckige Klammer am Listenanfang werden als Teil der Liste angesehen, alle anderen Sonderzeichen verlieren in der Liste ihre Bedeutung
( ) * Speichert das Muster zwischen \( und \) in einem speziellen Puffer.
  • In einer Zeile können bis zu neun solcher Puffer belegt werden.
  • In Substitutionen können sie über die Zeichenfolgen \1 bis \9 wieder benutzt werden
{ } * Steht für den Vorkommensbereich des unmittelbar vorhergehenden Zeichens.
  • \{n\} bezieht sich auf genau n Vorkommen,
  • \{n,\} auf mindestens n Vorkommen und
  • \{n,m\} auf eine beliebige Anzahl von Vorkommen zwischen n und m.
  • Dabei müssen n und m im Bereich zwischen 0 und 256 liegen
<\ Steht für ein Zeichen am Anfang (<) oder am Ende (>) eines Wortes
+ Steht für ein oder mehrere Vorkommen des vorhergehenden regulären Ausdrucks = \{1,\}
? Steht für kein oder ein Vorkommen des vorhergehenden Ausdrucks. = \{0,1\}
| Übereinstimmung, wenn entweder der vorhergehende oder der nachfolgende reguläre Ausdruck übereinstimmen
( ) Steht für die eingeschlossene Gruppe von regulären Ausdrücken

Trennzeichen

When entering a regular expression in a programming language, they may be represented as a usual string literal, hence usually quoted; this is common in C, Java, and Python for instance, where the regular expression re is entered as "re". However, they are often written with slashes as delimiters, as in /re/ for the regular expression re.

This originates in ed, where / is the editor command for searching, and an expression /re/ can be used to specify a range of lines (matching the pattern), which can be combined with other commands on either side, most famously g/re/p as in grep ("global regex print").

A similar convention is used in sed, where search and replace is given by s/regexp/replacement/ and patterns can be joined with a comma to specify a range of lines as in /re1/,/re2/.

This notation is particularly well-known due to its use in Perl, where it forms part of the syntax distinct from normal string literals. In some cases, such as sed and Perl, alternative delimiters can be used to avoid collision with contents, and to avoid having to escape occurrences of the delimiter character in the contents.

For example, in sed the command s,/,X, will replace a / with an X, using commas as delimiters.

Standards

The IEEE POSIX standard has three sets of compliance: BRE, ERE, and SRE for Basic, Extended, and Simple Regular Expressions. SRE is deprecated, in favor of BRE, as both provide backward compatibility. The subsection below covering the character classes applies to both BRE and ERE.

BRE and ERE work together. ERE adds ?, +, and |, and it removes the need to escape the metacharacters ( ) and { }, which are required in BRE. Furthermore, as long as the POSIX standard syntax for regular expressions is adhered to, there can be, and often is, additional syntax to serve specific (yet POSIX compliant) applications.

Although POSIX.2 leaves some implementation specifics undefined, BRE and ERE provide a "standard" which has since been adopted as the default syntax of many tools, where the choice of BRE or ERE modes is usually a supported option.

For example, GNU grep has the following options: "grep -E" for ERE, and "grep -G" for BRE (the default), and "grep -P" for Perl regular expressions.

Perl regular expressions have become a de facto standard, having a rich and powerful set of atomic expressions. Perl has no "basic" or "extended" levels, where the ( ) and { } may or may not have literal meanings.

They are always metacharacters, as they are in "extended" mode for POSIX. To get their literal meaning, you escape them. Other metacharacters are known to be literal or symbolic based on context alone.

Perl offers much more functionality: "lazy" regular expressions, backtracking, named capture groups, and recursive patterns, all of which are powerful additions to POSIX BRE/ERE.

POSIX Basic Regular Expression (BRE)

Bei der Standard Basic Regular Syntax (BRE) müssen die Metazeichen( ) und { } maskiert werden, \(\) und \{\}, bei der Extended Regular Syntax (ERE) nicht.

Metacharacter Description
. Matches any single character (many applications exclude newlines, and exactly which characters are considered newlines is flavor-, character-encoding-, and platform-specific, but it is safe to assume that the line feed character is included). Within POSIX bracket expressions, the dot character matches a literal dot. For example, a.c matches "abc", etc., but [a.c] matches only "a", ".", or "c".
[ ] A bracket expression. Matches a single character that is contained within the brackets. For example, [abc] matches "a", "b", or "c". [a-z] specifies a range which matches any lowercase letter from "a" to "z". These forms can be mixed: [abcx-z] matches "a", "b", "c", "x", "y", or "z", as does [a-cx-z].

The - character is treated as a literal character if it is the last or the first (after the ^, if present) character within the brackets: [abc-], [-abc]. Note that backslash escapes are not allowed. The ] character can be included in a bracket expression if it is the first (after the ^) character: []abc].

[^ ] Matches a single character that is not contained within the brackets. For example, [^abc] matches any character other than "a", "b", or "c". [^a-z] matches any single character that is not a lowercase letter from "a" to "z". Likewise, literal characters and ranges can be mixed.
^ Matches the starting position within the string. In line-based tools, it matches the starting position of any line.
$ Matches the ending position of the string or the position just before a string-ending newline. In line-based tools, it matches the ending position of any line.
( ) Defines a marked subexpression. The string matched within the parentheses can be recalled later (see the next entry, \n). A marked subexpression is also called a block or capturing group. BRE mode requires \( \).
\n Matches what the nth marked subexpression matched, where n is a digit from 1 to 9. This construct is vaguely defined in the POSIX.2 standard. Some tools allow referencing more than nine capturing groups.
* Matches the preceding element zero or more times. For example, ab*c matches "ac", "abc", "abbbc", etc. [xyz]* matches "", "x", "y", "z", "zx", "zyx", "xyzzy", and so on. (ab)* matches "", "ab", "abab", "ababab", and so on.
{m,n} Matches the preceding element at least m and not more than n times. For example, a{3,5} matches only "aaa", "aaaa", and "aaaaa". This is not found in a few older instances of regular expressions. BRE mode requires \{m,n\}.
Beispiele
.at * matches any three-character string ending with "at", including "hat", "cat", and "bat".
[hc]at * matches "hat" and "cat".
[^b]at * matches all strings matched by .at except "bat".
[^hc]at * matches all strings matched by .at other than "hat" and "cat".
^[hc]at * matches "hat" and "cat", but only at the beginning of the string or line.
[hc]at$ * matches "hat" and "cat", but only at the end of the string or line.
\[.\] * matches any single character surrounded by "[" and "]" since the brackets are escaped, for example: "[a]" and "[b]".
s.* * matches any number of characters preceded by s, for example: "saw" and "seed".

POSIX Extended Regular Expression (ERE)

The meaning of metacharacters escaped with a backslash is reversed for some characters in the POSIX Extended Regular Expression (ERE) syntax.

With this syntax, a backslash causes the metacharacter to be treated as a literal character. So, for example, \( \) is now ( ) and \{ \} is now { }. Additionally, support is removed for \n backreferences and the following metacharacters are added:

Metacharacter Description
? Matches the preceding element zero or one time.

For example, ab?c matches only "ac" or "abc".

+ Matches the preceding element one or more times.

For example, ab+c matches "abc", "abbc", "abbbc", and so on, but not "ac".

| The choice (also known as alternation or set union) operator matches either the expression before or the expression after the operator.

For example, abc|def matches "abc" or "def".

Beispiele
[hc]+at * matches "hat", "cat", "hhat", "chat", "hcat", "cchchat", and so on, but not "at".
[hc]?at * matches "hat", "cat", and "at".
[hc]*at * matches "hat", "cat", "hhat", "chat", "hcat", "cchchat", "at", and so on.
cat|dog * matches "cat" or "dog".
$ echo Hallo | grep [[:upper:]ab]
Hallo* trifft Großbuchstaben und die Kleinbuchstaben “a” und “b”

Weitere Beispiele Ein wichtiges Element der REs ist das Platzhalterzeichen ".". Es ist Platzhalter für jedes beliebige Zeichen, also numerische, alphabetische oder Sonderzeichen. Ein "." steht für ein einziges beliebiges Zeichen.

echo "ihr Name ist Mayer, sein Name ist Meier" | sed -n '/Ma.er/p'
  • die RE "Ma.er" passt auf "Mayer", daher ist die Suchbedingung erfüllt.
  • Nicht die Ergebnismenge "Mayer", sondern die ganz Zeile wird ausgeben.
echo "ihr Name ist Mayer, sein Name ist Meier" | sed -n '/M..er/p'
  • "Mayer" und "Meier" passen, es gibt also 2 Ergebnismengen.
  • Wie im ersten Fall wird die ganze Zeile ausgegeben.
  • Die Anzahl der Ergebnismengen erfährt man nicht.

Die Anzahl der Platzhalterzeichen lässt sich weiter spezifizieren. Leider müssen die geschweiften Klammern, "+" und "?" escaped werden durch Voranstellung des "\".

.\{n\} # n mal "."
.\{,n\} # 0-n mal "."
.\{n,\} # n bis unendlich mal "."
.\{m,n\} # m-n mal "."
.* # 0 bis unendlich mal "."
.\+ # 1 bis unendlich mal "."
.\? # 0-1 mal "."
echo "ihr Name ist Mayer, sein Name ist Meier" | sed -n '/M.\{2\}er/p'
  • die RE "M..er" ist identisch mit "M.\{2\}er"
  • die Klammern müssen "escaped" werden, damit sed sie richtig interpretiert: \{...\}
echo "ihr Name ist Mayer, sein Name ist Meier" | sed -n '/M.*er/p'*
  • Es gibt mehrere Ergebnismengen:
# Mayer
# Mayer, sein Name ist Meier
# Meier
  • Es gilt (2), weil es die größte Ergebnismenge ist

Unabhängig davon, ob keine, eine oder mehrere Ergebnismengen gefunden werden, wird immer die gesamte Zeile ausgegeben. Wenn man nur die effektive (größte) Ergebnismenge sehen will, muss man egrep mit der "-o" Option zu Hilfe nehmen

echo "ihr Name ist Mayer, sein Name ist Meier" | egrep -o 'M.*er'
  • Die RE steht anders als bei sed innerhalb von einfachen Hochkommta.
  • -o bewirkt, dass nur die effektive Ergebnismenge angezeigt wird

Die effektive Ergebnismenge lässt sich auch durch den s-Befehl herausbekommen:

echo "ihr Name ist Mayer, sein Name ist Meier" | sed 's/M.*er/X/g'

Beim Suchen & Ersetzen wird die effektive Ergebnismenge durch "X" ersetzt

Der einfachste Reguläre Ausdruck

Die einfachste RE besteht aus einem Suchstring ohne weitere Deskriptoren, also z. B.  dem Wort "Mayer".

echo "ihr Name ist Mayer, sein Name ist Meier" | sed 's/Mayer/X/g'

"Mayer" ist effektive Ergebnismenge und wird durch "X" ersetzt

Beachten Sie, dass die folgende RE ein anderes Ergebnis liefert:

echo "ihr Name ist Mayer, sein Name ist Meier" | sed 's/.*Mayer.*/X/g'

diese RE trifft auf die gesamte Zeile zu, nicht nur auf "Mayer"!

Mustererkennung

In der folgenden Tabelle wird gezeigt, in welchen Unix-Tools welche Zeichen zur Verfügung stehen.

ed ex sed awk grep egrep
. X X X X X X Ein beliebiges Zeichen
* X X X X X X Kein, ein oder mehrere Vorkommen des vorhergehenden Ausdrucks.
^ X X X X X X Zeilenanfang
$ X X X X X X Zeilenende
\ X X X X X X Hebt die Sonderbedeutung des folgenden Zeichens auf.
[ ] X X X X X X Ein Zeichen aus der Gruppe
[^ ] X X X X X X Kein Zeichen aus der Gruppe
( ) X X X Speichert das Muster zur späteren Wiederholung.
{ } X X X Vorkommensbereich
< X X Wortanfang
> X X Wortende
+ X X Ein oder mehrere Vorkommen des vorhergehenden Ausdrucks.
? X X Kein oder ein Vorkommen des vorhergehenden Ausdrucks.
| X X Trennt die für die Übereinstimmung verfügbaren Alternativen.
( ) X X Gruppiert Ausdrücke für den Test.

Zeichenliterale

Diejenigen Zeichen, die direkt (wörtlich, literal) übereinstimmen müssen, werden auch direkt notiert.

Je nach System gibt es auch Möglichkeiten, das Zeichen durch den * Oktalcode (\ooo)

  • Hexadezimalcode (\ooo bzw. \xhh) oder die
  • hexadezimale Unicode-Position (\uhhhh)

anzugeben.

Ein beliebiges Zeichen

Ein Punkt (.) bedeutet, dass an seinem Platz ein (fast) beliebiges Zeichen stehen kann.

Die meisten RegExp-Implementierungen sehen standardmäßig Newline (Zeilenumbruch) nicht als beliebiges Zeichen an.

In einigen Programmen kann mithilfe des sogenannten Single-Line-Modifiers s (zum Beispiel in /foo.bar/s) ebendies erreicht werden.