orm@doc-tcpip.org | Erstellt: Mai 1999 - Letzte Modifikation: Februar 2005 |
Reguläre Ausdrücke sind ein mathematisches Konzept, mit dem man unter Benutzung von definierten Platzhaltern logische Zusammenhänge ausdrücken kann. In der Informatik nutzt man Reguläre Ausdrücke, um Muster zu erkennen und zu filtern.
Es gibt Literale, Metacharaktere, Charakterklassen und Metasequenzen.
Je nach benutztem Werkzeug (grep, egrep, Perl ...) unterscheiden sich die Implementationen der Regulären Ausdrücke gewaltig, sowohl im Umfang wie auch in der Funktion. Es gibt keinen Standardsatz an Regulären Ausdrücken; nur bei einfachen Ausdrücken kann man von einer gewissen Portabilität ausgehen - so sind die gängigen Metacharaktere mittlerweile quasi-Standard. Bei gepflegten Werkzeugen werden zusätzlich die Funktionalitäten regelmäßig erweitert, da alle Programmierer immer fleißig abgucken.
Es ist wichtig, sich klarzumachen, daß ein Regulärer Ausdruck nicht in seiner Gesamtheit bewertet und erkannt wird. Der Vergleich erfolgt Position für Position, und beim ersten Unterschied wird abgebrochen. So wird der Reguläre Ausdruck ^orm so Verglichen: "Der Anfang einer Zeile, gefolgt von einem kleinen o, gefolgt von einem kleinen r, gefolgt von einem kleinem m".
egrep, grep, fgrep -i: case insensitiv
Ein Metazeichen bezieht sich immer auf ein vorangehendes Zeichen; ein Ausnahme bilden die Metazeichen, die eine Position darstellen (Positionsanker). Das links stehende (vorangehende) Zeichen kann auch eine Gruppe oder Klasse sein. Jedenfalls immer eine und nur eine Position.
Ckarakterklassen sollte man als Regulären Ausdruck in einem Regulären Ausdruck betrachten. Man kann in einer Charakterklasse Literale und Funktionen zusammenfassen. Eine bestimmte Position wird dann gegen eine definierte Gruppe von Zeichen verglichen.
So findet [ab] entweder "a" oder "b", also immer nur ein Zeichen pro Klammerausdruck. In diesem Fall hätte man auch eine Auswahl angeben können: (a|b). Mit folgenden Charakterklassen wird das ganze klarer: H[123456] (bzw. H[1-6]) findet H1, H2 etc.
So ist zB. [A-Fa-f0-9] praktisch, wenn man mit hexadezimalen Zahlen arbeitet.
Probleme gibt es dann, wenn in einer Charakterklasse Metazeichen auftauchen - schließlich kann es ja sein, daß man die Funktion des Metazeichen haben möchte oder aber die wörtliche Bedeutung. In einer Charakterklasse sind Metacharaktere in der Regel Literale. Die eckigen Klammern heben die spezielle Bedeutung der Metcharaktere auf. Eine Ausnahme ist der Bindestrich. Er zeigt einen Bereich an und ist nur an erster Stelle als Literal anzusehen: [0-9_!.?] findet eine Zahl oder die Sonderzeichen _, !, ., ?. Möchte man auch den Bindestrich finden, so muß dieser an der ersten Stelle stehen - nur dort wird er wörtlich genommen: [-0-9_!.?].
Den Inhalt einer Charakterklasse kann man negieren: [^1-6] findet jedes Zeichen, daß nicht 1, 2, 3, 4, 5, oder 6 ist. Das Caret ist also ein weiterer Metacharakter, der seine speziellen Eigenschaften in einer Charakterklasse behält - allerdings wieder nur an erster Stelle; sonst wird es als Literal gewertet.
z[^w] findet alle Stellen, wo "z" nicht von einem "w" gefolgt wird. Es muß aber ein Zeichen folgen.
Der Punkt ist die Charakterklasse "ein beliebiges Zeichen". Taucht der Punkt in einer Charakterklasse auf, so ist er ein Literal. Nochmal zur Stellung in einer Charakterklasse:
Wie findet man ein Datum? Es gibt schließlich eine Reihe Formate wie 05.03.2002, 05/03/2002 oder 05-02-2002. Man kann das Problem mit Punkten angehen: 05.03.2002. Der Punkt als Charakterklasse "beliebiges Zeichen" findet alle Zeichen, auch Zahlen etc. an den entsprechenden Stellen.
Daher bildet man präziser die Charakterklasse [-./].
Wie findet man einen 24-Stunden Zeitstempel (07:34:44)? Dazu ein paar Möglichkeiten:0?[0-9]|1[0-9]|2[0-3] oder [01]?[0-9]|2[0-3] oder [01]?[4-9]|[012]?[0-3].
Will man einzelne Buchstaben finden, so kann man eine Charakterklasse, eine Oder-Verknüpfung oder eine Alternative in einer Klammer angeben. Das Ergebnis ist gleich, aber auf ganz unterschiedliche Weise zustande gekommen: Die Charakterklasse "iy": me[iy]er, "meier" oder "meyer": meier|meyer und die Alternative: me(i|y)er. Das ist auch nützlich beim Auswerten von Mailfiles: ^(From|Subject|Date):.
Sind Kombinationen von Metazeichen, die eine neue Funktion bezeichnen. Im Prinzip also nur eine nötige Erweiterung der Metazeichen, einfach wiel nicht genügend Zeichen zur Verfügung stehen. Auch hier gilt wieder, das nicht alle Werkzeuge alle geschilderten Metasequenzen auch tatsächlich implemetieren.
\< bzw. \> bezeichnet Wortenden. Der Reguläre
Ausdruck \
Viele Implementationen stellen sogenannte Backreferences zur Verfügung. Dabei kann in einem Ausdruck Bezug genommen werden auf ein vorher erkanntes Muster.
Ein Beispiel: \<([A-Za-z]+) +\1\>
Dieser Ausdruck findet alle doppelten Worte. Der Ausdruck in den
runden Klammern ist ein beliebiges Wort; er wird in der Variable
$1 gespeichert - das gilt generell für alle Ergebnisse
der Ausdrücke in runden Klammern.
Mit der Metasequenz \1 wird sich auf diese Variable bezogen.
Das Wort muß also nochmal vorkommen. Das Plus erlaubt beliebige
(mindestens ein) Leerzeichen. Sind mehrere Klammerterme vorhanden,
so wird hochgezählt: (xxx) (yyy) (zzz) \1 \2 \3.
Einen in Anführungsstrichen eingefassten Ausdruck finden: "[^"]*". Dabei steht [^"] für Zeichen, die nicht """ (Anführungsstriche) sind. Das Sternchen erlaubt beliebige Mengen davon.
Perl hat eine ausgesprochen umfangreiche Implementation der Regulären Ausdrücke. Hier sind ein paar Perl Basics zusammengetragen.
Finden doppelter Worte im Text:
$/ = ".\n" while (<>) { next if !s/\b(a-z]+)((?:\s|<[^>]+>)+)(\1\b)/\e [7m$1\e[m$2\e[7m$3\e[m/ig; s/^(?:[^\e]*\n)+//mg; s/^/$ARGV: /mg; print }
Sind nur Zahlen in $reply?
if ($reply =~ m/^[0-9]+$/) { print "nur Zahlen \n"; } else { print "nicht nur Zahlen \n"; }
Eingaben:
print "Eingabe des Wertes: \n"; $eingabe =; chomp($eingabe); if ($eingabe =~ m/^[+-]?[0-9]+(\.[0-9]*)?$/) { ..... Optional + oder - Beliebige Zahlen, mindestens eine Optional beliebige Dezimalstellen oder ein Punkt alleine Erlaubt 45, -0.74, +1002 Alles in ( ) (runden Klammern) wird in eine Variable gefasst. Man kann es dann mit den Variablen $1, $2, ... auslesen und benutzen. Das kann man verhindern, indem man (?: ) schreibt. Der Klammerausdruck wird dann normal ausgewertet, aber nicht in die Variable geschrieben (er zählt dann auch nicht).String Vergleich: eq:
if ($type eq "c" or $type eg "C") oder: m/c/i ==> finde c CaseinsensitivAusdrucken:
printf "%.2f C is %.2f F\n", $celsius, $fahrenheit;Kurzformen für Perl
- \t Tabulator
- \n Neue Zeile
- \r Carriage Return
- \s Jeder "whitespace" (space, tab, newline, formfeed)
- \S alles, nur nicht \s
- \w [a-zA-Z0-9_] (zB. \w+ ==> ein Wort)
- \W alles, was nicht \w ist ==> [^a-zA-Z0-9_]
- \d [0-9]
- \D alles, was nicht \d ist ==> [^0-9]
- \i case insensitiv
Formbrief
Lieber =VORNAME= ... $name = "Seppel"; $brief =~ s/=VORNAME=/$name/g;Einlesen
while ($line = <>) { if ($line =~ m/^start: (.*)/i) { $anfang = $1; } if ...... Beenden: if [$line =~ m/^\s*$/) { last; ==> Ende der while Schleife } Mail einlesen und mit > versehen: Literale klammern ^Start: (\S+) \(([^()]*)\) $1 keine Klammern im Ausdruck while ($line = <>) { print "> $line"; } $line =~ s/^/ > /; print $line; Ersetzt den Zeilenanfang (^) als Positionsanker mit >.Fehlermeldungen
Sind alle Variablen gesetzt: if ( not defined ($variable1) or not defined ($variable2)) { die "Mist"; }Suchen nach Positionen im Text - Lookaround
Beim Lookaround wird kein Text "verbraucht". Die erkannten Muster werden nur zur Bestimmung einer Position genutzt.
- Lookahead: (?= ) Negativ: (?! )
- Lookbehind: (?<= ) Negativ: (?
Ein Beispiel: Michel soll Michael werden: Man sucht die Position zwischen Mich und el, fügt dann an dieser Stelle ein a ein:
(?<=\bMich)(?=el\b) s/(?<=\bMich)(?=el\b)/a/g
[ Allgemein | UNIX | AIX | TCP-IP | TCP | ROUTING | DNS | NTP | NFS | FreeBSD | Linux | RPi | SMTP | Tracing | GPS | LW ]
Copyright 2001-2021 by Orm Hager - Es gilt die GPL
Feedback bitte an: Orm Hager (orm@doc-tcpip.org )