210 likes | 338 Views
Die Skriptsprache Perl (3). Wolfgang Friebel DESY Zeuthen. Anmerkungen zu Teil 2. Wahrheitswerte: 0, ‘0’, “0”, ‘’, “”, () und undef sind falsch Wortzählung: while ( <> ) { chomp; for ( split ) { # split(/s+/, $_) $anzahl{$_}++; # Interpunktion entfernen? }
E N D
Die Skriptsprache Perl (3) Wolfgang Friebel DESY Zeuthen
Anmerkungen zu Teil 2 • Wahrheitswerte: 0, ‘0’, “0”, ‘’, “”, () und undef sind falsch • Wortzählung: while ( <> ) { chomp; for ( split ) { # split(/\s+/, $_) $anzahl{$_}++; # Interpunktion entfernen? } } # danach Ausgabe von %anzahl Einzeiler mit -p und -n (unter NT) (LF->CR/LF, grep) perl -pe ”s/\012/\n/” unix.txt > dos.txt perl -ne ”print if /Suchtext/” Datei
4. Reguläre Ausdrücke • zum Suchen und Ersetzen von Strings • werden auch in anderen Programmen benutzt awk, sed, vi, egrep (Untermenge von perl-regex) • Suchen mit dem Match-Operator m/regex/ Klammern wie bei q, qw, .. (d.h. auch m(), m[], m!!) Bei / als Begrenzer kann m entfallen (/regex/) • Ersetzen mit Substitute-Operator s/regex/string/ • Optionen modifizieren Operatorverhalten z.B. m/regex/i und s/regex/string/g
Suchen und Ersetzen ohne Regex • Suchen mit index: (index string, substring, offset) $found = 1 if index ($_, ”string”) >= 0; • Ersetzen mit substr: (substr string, offset, length) $was = ’Hahn’; substr($was, 0, 1) = ’W’; substr($was, -1, 1) = ’r’; • Funktion substr kann links und rechts von = stehen • substr und index sind meist schneller als Regex, eventuell ist die Lesbarkeit von Regex besser (perl5.005 optimiert konstante Strings -> index)
Suchen in Tabellen • kann ohne Regex vorteilhafter sein • bei fester Zuordnung Spalten/Inhalt • keine Probleme, wenn Spalten zusammenfließen • @feld = unpack muster, string string wird nach Anweisung in Muster zerhackt Muster z.B.: “A10xA5“ (10 Char, 1 ignoriertes, 5Char) Verwendung anderer Typen, dann keine fixe Spalten Siehe manpage (perlfunc)
Worin wird gesucht • Bei m// und s/// wird in $_ gesucht/ersetzt • Verhalten durch Pattern binding Operator änderbar $ok = 1 if $a =~ /string/; #Suche in $a $notok = 1 if $b !~ /string/; #Suche in $b $ok = 1 if $c =~ s/hü/hott/;#Ersetze in $c • Resultat ist bei Erfolg wahr für =~, falsch für !~ • Listkontext: gefundene/ersetzte Strings als Resultat ($program = $0) =~ s(^.*/)(); #Scriptname
Elemente regulärer Ausdrücke • Alle ASCII Zeichen (Zeichen \|()[{^$*+?. nur mit \) • Metazeichen (Zeichen \|()[{^$*+?. und andere mit \) • Klassen von Zeichen, z.B.: [yYjJ] [a-z0-9] \d • Alternativen, durch | markiert, z.B.: /quit|exit/ • Beginn und -ende (^ und $) und andere Begrenzer • Durch Klammerung (...) markierte Unterausdrücke • Wiederholungsfaktoren ? + {n} {min,max} • das ”beliebige” Zeichen . (nicht \n, siehe Option s) • Assertions (erfüllte Bedingungen), beginnen mit (?
Kommentare • Reguläre Ausdrücke relativ unleserlich • Möglichkeit der Kommentierung mit (?# das ist ein Kommentar) • Verwendung von Option x • Leerraum wird ignoriert, Kommentare wie gewohnt mit # möglich m { a|b # eine Alternative, a oder b }x
Klassen von Zeichen • Aufzählung: [jJyY] oder [^jJyY] (alles außer jJyY) • Aufzählung mit Bereichen: [a-fA-F] • Metazeichen, die Klasse definieren: \w word char [a-zA-Z_0-9] \W nonword char \d digit [0-9] \D nondigit \s whitespace [ \t\n\r\f] \S non-whitespace • Sonderzeichen: \a \e \f \n \r \t (beep, ESC, formfeed, newline, CR, tab) \033 \x1b \cC (ESC, ESC, CTRL-C)
Wiederholungen • Zeichen (oder Zeichengruppe) kann mit Wiederholungsfaktor versehen werden • * 0 oder mehrmals, entspricht {0,} • ? 0 oder 1 mal, entspricht {0,1} • + mindestens 1 mal, entspricht {1,} • {min,max} mindestens min, höchstens max mal • {n} entspricht {n,n} • {n,} mindestens n mal
Optionale Ausdrücke • Ausdrücke, die mehrere Möglichkeiten zulassen: • Alternativen mit | • Ausdrücke mit ?, *, +, {min,max} oder {min,} • Bearbeitung von Alternativen von links nach rechts • andere optionale Ausdrücke sooft wie möglich • Ausdrücke sind “greedy - gierig, gefräßig” • Änderung des Verhaltens durch nachgestelltes ? • optionale Ausdrücke werden zunächst übergangen • non-greedy, auch minimal matching
Maximales Matching • Suche in ”Apfel,Birne,Kirsche,Pflaume” /,.*,/ # greedy, maximal matching • Suche nach erstem Komma (5*falsch, 1*wahr) • Suche nach .* (Bis zum Ende wahr, Alternativen) • Suche nach Komma (falsch) • Nimm letzte Alternative (bis m, dann Komma, falsch) • Weiter so (Backtracking), bis Komma gefunden • daher Resultat:”,Birne,Kirsche,”
Minimales Matching • Suche in ”Apfel,Birne,Kirsche,Pflaume” /,.*?,/ # non greedy, minimal matching • Suche nach erstem Komma (5*falsch, 1*wahr) • Übergehe .*, suche nach Komma (falsch) • Nimm letzte Alternative (., weiter mit Komma, falsch) • Weiter so (5 mal) bis Komma gefunden • daher Resultat:”,Birne,” /,[^,]*,/ # non greedy, schnellste Suche • Ausdruck fast immer wahr, kommt schnell zum Ende
Backtracking Probleme • Regex arbeitet stur nach vorgenannten Regeln • Bei geschachtelten optionalen Ausdrücken Gefahr: • (\d+)*a #Suche z.B. nach 17a • String aus 80 Ziffern: + führt zu 80, 79, ... Zeichen • * führt zu 80,79,... mal 1 Zeichen + 40,39,... mal 2... • Regex muß immer weitermachen, da a fehlt • Exponentielle Suche mit riesiger Rechenzeit für ”einfaches” Problem • keine geschachtelte optionale (auch |) Ausdrücke!
Subpatterns • Definiert durch runde Klammern um Teilausdrücke • Innerhalb des Regex Rückbezug mit \1 \2 .. möglich • Nach erfolgreichem Match als $1 $2 .. gefüllt • Gilt nicht für Assertions (?...) (siehe später) • Besonders: (?:) wirkt wie (), aber kein Rückbezug /,(.*?),(.*?),(.*?)/;# $1=’Apfel’,$2=’Birne’ s/^([^ ]*) *([^ ]*)/$2 $1/;# swap words
Die Variablen $`, $& und $’ • Enthalten String, in dem gesucht wird: • $`: vorderer Teil, der nicht gematcht hat • $&: Teil, auf den der Regex paßt • $´: Rest des Strings • Variablen werden nur gefüllt, wenn auch benutzt • einmalige Benutzung triggert Füllung überall
Assertions • Ausdrücke, die erfüllt werden müssen (Länge 0!) • Einfachste Assertions: ^ und $ (oder \A und \Z) • Weitere Assertions: \b Wortgrenze (zwischen \w und \W) \B keine Wortgrenze • Nicht besprochen: lookahead assertion (?=...) (?!...) lookbehind assertion (5.005) (?<=...) (?<!...) und andere Exoten für obfuscated perl contest
Optionen • Strings mit Newlines: • .* endet bei \n, da \n nicht in . • Änderung durch Option s: . erfaßt auch newline • ^ und $ nur am Stringanfang und -ende wahr • mit Option m ^ und $ auch an Zeilenanfang/ende wahr • Ignorieren von Klein/Großschreibung: Option i • Wiederholen von Suchen/Ersetzen: Option g • dann Resultat = Anzahl erfolgreicher Operationen • im Listkontext Resultat = gefundene/ersetzte Strings
Regex in split • split ist die einzige weitere Funktion mit Regex split pattern, string • zerlegt String gemäß pattern • pattern ist ’regex’ oder /regex/, nicht ”regex” • pattern, das ’’ matcht, zerlegt String in Zeichen @digits = split //, ”0123456789”; • zusätzliche Elemente aus () Ausdrücken erzeugt • Verarbeitung von “Config-files“ (key = val Zeilen) %conf = split /\s*=\s*(\S+)\n/, $zeilen);
Hausaufgaben • Schreibe ein Programm, das die Zeile ”abc ”x10 mit folgenden Methoden zerlegt: substr, pack, regex, split • Übe die Benutzung von substr als ”lvalue” (links von =) • Entferne Leerzeichen am Stringanfang und -ende (Idiom!) • Schreibe einen regex Ausdruck mit Kommentaren • Übe die Benutzung von $`, $&, $’ und $1, $2,… • Wieviele Teste sind in den Beispielen auf S. 12/13 nötig • Wie funktioniert das letzte Beispiel auf S.19 • Lies die manpage perlre