die skriptsprache perl (3) wolfgang friebel desy zeuthen
TRANSCRIPT
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 Regexsplit 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