Webapplicaties 1. Reguliere uitdrukkingen in Perl Regular Expressions in Perl.......................................................... 2 1.1 Inleiding Perl: een bestand inlezen en afbeelden ....................................................... 2 1.2 Eenvoudige voorbeelden van Regular Expressions ................................................... 3 1.3 De multipliers *, +, ?, {m,n} ...................................................................................... 3 1.3.1 De multiplier * ................................................................................................... 3 1.3.2 De multiplier + ................................................................................................... 3 1.3.3 De multiplier ? .................................................................................................... 3 1.3.4 De algemene multiplier {m, n} .......................................................................... 3 1.4 Single character patronen ........................................................................................... 4 1.4.1 Het patroon . ....................................................................................................... 4 1.4.2 Een character class ............................................................................................. 4 1.4.3 De negatie van een character class ..................................................................... 4 1.4.4 Een aantal concrete voorbeelden ........................................................................ 5 1.5 Anchoring Patterns ..................................................................................................... 5 1.6 Alternation .................................................................................................................. 5 1.7 lParentheses as memory ............................................................................................. 5 1.8 De =~ operator............................................................................................................ 5 1.9 Substitutions ............................................................................................................... 6 1.10 De split()-funtie .......................................................................................................... 7 1.11 De multi-line optie ..................................................................................................... 8 2. Regular Expressions toegepast in andere omgevingen ................ 9 2.1 Regular Expressions in Javascript .............................................................................. 9 2.1.1 String methods for pattern matching .................................................................. 9 2.1.2 RegExp methods for pattern matching ............................................................... 9 2.1.3 Een praktisch voorbeeld ................................................................................... 10 2.2 Regular Expressions in php ...................................................................................... 10 2.3 Regular Expressions in Asp/Vbscript ...................................................................... 11 2.4 Regular Expressions in … (zie luc :-D ) .................................................................. 11 Webapplicaties Reguliere uitdrukkingen in Perl 1. REGULAR EXPRESSIONS IN PERL Een reguliere uitdrukking of regular expression is een patroon, een sjabloon, dat vergeleken wordt met een string. Het resultaat van deze vergelijking is waar of vals. Als voorbereiding bekijken we eerst een aantal functies die op eenvoudige manier het omgaan met textbestanden toelaten op regel-niveau. 1.1 Inleiding Perl: een bestand inlezen en afbeelden Voor de oefeningen betreffende re zal het handig zijn dat we kunnen beschikken over een programma dat op eenvoudige wijze de regels van een bestand inleest en verwerkt. Aangezien een van de belangrijke functies van perl het verwerken van tekst is, zal dit natuurlijk gemakkelijk mogelijk zijn: #!/usr/bin/perl -w while (<>) { print $_; } Sla dit bestand op als oef1. Zet de permissies goed, bijv 755 en voer het bestand uit als: ./oef1 testdata. Hierbij is testdata de naam van een tekstbestand dat de testinformatie bevat. Het bovenstaande perl-programma leest met andere woorden het bestand, aangegeven door de commandline parameter, regel voor regel in de variabele $_ in. En beeldt die af met een printopdracht. We kunnen de zaak een beetje manipuleren door de array die de commandline parameters bijhoudt, zelf op te vullen: #!/usr/bin/perl -w @ARGV=("testdata"); print $ARGV[0]."\n\n"; while (<>) { print $_; } De instructie @ARGV=("testdata"); definieert de array ARGV met als enig element de string testdata. Deze instuctie is in php gelijkwaardig aan: $ARGV = array("testdata"); Het @-teken voor de veranderlijke duidt aan dat de veranderlijke een array is. De individuele elementen van de array spreek je in perl aan zoals in php, bijv.: $ARGV[0] Na het verwerken van de bestanden is de array @ARGV leeg. Door hem opnieuw te initialiseren kunnen we de lus naar believen opnieuw uitvoeren! #!/usr/bin/perl -w @ARGV=("testdata"); while (<>) { print $_; } @ARGV=("testdata"); while (<>) { print $_; } Om het textbestand om te zetten naar html volstaat het een beetje extra informatie toe te voegen: #!/usr/bin/perl -w @ARGV=("testdata"); while (<>) { print "<br>$_"; } Webapplicaties Reguliere uitdrukkingen in Perl 1.2 Eenvoudige voorbeelden van Regular Expressions De volgende reguliere uitdrukking, ingesloten tussen twee '/'-tekens, test of een string de letterreeks 'abc' bevat. #!/usr/bin/perl -w @ARGV=("testdata"); while (<>) { if (/abc/) { print "<br>$_"; } } 1.3 De multipliers *, +, ?, {m,n} De jokers verwijzen telkens naar het voorafgaande teken. De joker volgt met andere woorden altijd na het teken waarop het betrekking heeft. 1.3.1 De multiplier * De volgende code test of een string minstens één van de letterreeks 'ac', 'abc', 'abbc', 'abbbc', ... bevat. Dus: #'b' >= 0. #!/usr/bin/perl -w @ARGV=("testdata"); while (<>) { if (/ab*c/) { print "<br>$_"; } } 1.3.2 De multiplier + De volgende code test of een string minstens één van de letterreeks 'abc', 'abbc', 'abbbc', ... bevat. Dus: #'b' >= 1. #!/usr/bin/perl -w @ARGV=("testdata"); while (<>) { if (/ab+c/) { print "<br>$_"; } } 1.3.3 De multiplier ? De volgende code test of een string minstens één van de letterreeks 'ac', 'abc' bevat. Dus: #'b' <= 1. #!/usr/bin/perl -w @ARGV=("testdata"); while (<>) { if (/ab?c/) { print "<br>$_"; } } 1.3.4 De algemene multiplier {m, n} De volgende code test of een string de letterreeks 'abbc' bevat. Dus: #'b' = 2. #!/usr/bin/perl -w @ARGV=("testdata"); while (<>) { if (/ab{2}c/) { print "<br>$_"; } } De volgende code test of een string minstens één van de letterreeks 'abbc', 'abbbc' bevat. Dus: 2 <= #'b' <= 3. Webapplicaties Reguliere uitdrukkingen in Perl #!/usr/bin/perl -w @ARGV=("testdata"); while (<>) { if (/ab{2,3}c/) { print "<br>$_"; } } Als het tweede argument niet ingevuld is, dan is het tweede argument gelijkwaardig aan oneindig. De volgende code test bijgevolg of een string minstens één van de letterreeks 'abbc', 'abbbc', 'abbbbc', ... bevat. Dus: 2 <= #'b'. #!/usr/bin/perl -w @ARGV=("testdata"); while (<>) { if (/ab{2,}c/) { print "<br>$_"; } } Je kan nu gemakkelijk inzien dat de volgende tabel geldig is: korte notatie algemene notatie * {0,} + {1,} ? {0,1} 1.4 Single character patronen 1.4.1 Het patroon . Het single character patroon . komt overeen met ieder teken behalve het newline-teken. De volgende patronen zijn met andere woorden geldig: /./ aanvaard alle niet lege strings /.?/ aanvaard alle strings, dus ook de lege string /a.{2}c/ aanvaard alle strings die 'aaac' of 'abbc' of 'accc', ... bevatten /.{10}/ aanvaard alle strings die minstens 10 tekens bevatten. /d{2}.*l{2}/ aanvaard alle strings die twee opeenvolgende d’s bevatten gevolgd door een aantal willekeurige tekens en twee opeenvolgende l'en. Voorbeeld: onmiddellijk 1.4.2 Een character class Dit is een groep van elementen. Er wordt getest of het teken tot deze groep behoort. Een character class wordt afgebakend door vierkant haken. /[AEIOU]/ de string bevat een klinker in hoofdletter /[aeiouAEIUO]/ de string bevat een klinkers in hoofd- of kleine letters /[aeiou]{2}/ de string bevat twee opeenvolgende klinkers, bijv.: uil /[0123456789]/ de string bevat een getal /[0-9]/ Idem /\d/ Idem /[a-zA-Z] de string bevat een hoofd- of kleine letter uit het alfabet /[a-z][0-9]/ de string bevat een letter gevolgd door een getal /[a-z][0-9]{5}/ de string bevat een letter gevolgd door vijf getallen, bijv. een artikelnummer /[a-z]\d{5}/ Idem 1.4.3 De negatie van een character class Bij deze manier van werken noemen we niet de elementen op die tot de klasse behoren, maar de elementen die er niet toe behoren. Op deze manier van werken voegen we evt. elementen tot de klasse toe waaraan we zelfs niet gedacht hebben. Webapplicaties Reguliere uitdrukkingen in Perl /[^0-9]/ de string bevat een teken dat geen getal is. Let echter op, een newline, \n voldoet ook aan deze voorwaarde! /\D/ Idem /[0-9][^aeiouAEIUO]/ de string bevat een getal gevolgd door een niet klinker 1.4.4 Een aantal concrete voorbeelden /[a-zA-Z.]{1,}@[a-zA-Z]{1,}\.[a-zAZ]{2,3}/ /[1-9][0-9]{0,2}(\.[0-9]{3})+,[0-9]{2}/ de string bevat een e-mail adres de sting bevat een getal, bijvoorbeeld een bedrag in euro. Let op het \-teken voor het punt. Hierdoor verliest het punt zijn betekenis als single character patroon. 1.5 Anchoring Patterns Anchoring Pattern Betekenis ^ Duidt het begin van de string aan in het patroon $ Duidt het einde van de string aan in het patroon Zie hieronder een aantal voorbeelden: /^abc/ de string begint met abc /abc$/ de string eindigt op abc /^a.*3/ de string begint met a en bevat een 3 /3.*c$/ de string bevat een 3 en eindigt op c /^a.*3.*c$/ de string begint met a, bevat een 3 en eindigt op c 1.6 Alternation Dit is opnieuw een groep waarbij één element uit de groep in de string moet voorkomen. Indien alle elementen van de groep enkelvoudige karakters zijn, dan kan je beter gebruik maken van een single character class. In dit opzicht zijn de volgende opgaven soms een beetje dubbelzinnig /a|b|c/) de string bevat een a, b of c /a(b|c)/ de string bevat ab of ac /^(aa|AA)/) de string bevat een aa of AA /Fred|Barney/ de string bevat Fred of Barney 1.7 lParentheses as memory Door haakjes te gebruiken in een reguliere uitdrukking, sla je de waarde tussen de haakjes op in een variabele, typisch \1 ($1 in php) die je daarna opnieuw kan gebruiken #!/usr/bin/perl -w $_="12a12"; if (/([0-9]*)[a-z]\1/) { print "<br>de string bevat twee keer hetzelfde getal $1\n"; } $_="512a612"; if (/([0-9]*)[a-z]\1/) { print "<br>de string bevat twee keer hetzelfde getal $1\n"; } else { print "<br>de string bevat het getal $1 slechts één keer!\n"; } 1.8 De =~ operator Heel dikwijls zal de string die we willen testen niet in de $_-variabele zitten. We kunnen de logische uitdrukking van voorheen dan als volgt herschrijven: Webapplicaties Reguliere uitdrukkingen in Perl #!/usr/bin/perl -w $a = "abc123C" if ($a =~ /^abc/) { print "<br> \$a begint met abc!"; } Vergelijk ook eens de volgende voorbeelden, let hierbij in het bijzonder op het hooflettergebruik: #!/usr/bin/perl -w $a = "abc123C" if ($a =~ /^ABC/) { print "<br> \$a begint met abc!"; } en #!/usr/bin/perl -w $a = "abc123C" if ($a =~ /^ABC/i) { print "<br> \$a begint met abc!"; } 1.9 Substitutions In het volgende script wordt de test vervangen door oefening in de huidige lijn $_. #!/usr/bin/perl -w $_ = "hallo dit is een test"; print ; print "\n"; s/test/oefening/; print ; print "\n\n"; Of bijvoorbeeld test vervangen door examen. Let op de print-functie die eveneens $_ gebruikt! #!/usr/bin/perl -w $_ = "hallo dit is een test"; print ; print "\n"; s/test/examen/; print ; print "\n\n"; We mogen gerust variabelen gebruiken in een vervanging. De variabele wordt dan eerst vervangen door haar waarde, alvorens de bewerking uitgevoerd wordt. #!/usr/bin/perl -w $_ = "hallo dit is een test"; $a = "quiz"; print ; print "\n"; s/test/$a/; print ; print "\n\n"; In het script hierponder wordt de eerste letter e vervangen door de letter x. #!/usr/bin/perl -w $_ = "hallo dit is een test"; print ; print "\n"; s/e/x/; print ; print "\n\n"; Door achteraan de optie g op te nemen, worden alle letters e in de opgegeven string vervangen door x. #!/usr/bin/perl -w $_ = "hallo dit is een test"; print ; print "\n"; s/e/x/g; print ; print "\n\n"; Merk op dat deze bewerking hoofdletter-gevoelig is! #!/usr/bin/perl -w $_ = "hallo dit is een GOEDE test"; print ; print "\n"; s/e/x/g; print ; print "\n\n"; Dit kunnen we natuurlijk gemakkelijk oplossen door achteraan de schakeloptie i op te nemen. #!/usr/bin/perl -w $_ = "hallo dit is een GOEDE test"; Webapplicaties Reguliere uitdrukkingen in Perl print ; print "\n"; s/e/x/gi; print ; print "\n\n"; Willen we niet de huidige lijn bewerken maar een stuk tekst opgeslagen in een willekeurige variabele? Dan maken we opnieuw gebruik van de ‘=~’-operator. Deze operator is hier echter een toekennings-operator en geen vergelijkingsoperator! #!/usr/bin/perl -w $s = "hallo dit is een test"; print "$s\n"; $s =~ s/test/oefening/; print "$s\n\n"; Het volgende script laat de tekst in de variabele $s voorafgaan door een ‘<br>’-tag. #!/usr/bin/perl -w $s = "hallo dit is een test"; print "$s\n"; $s =~ s/^/<br>/; print "$s\n\n"; Voor het omwisselen van twee woorden heb je bijvoorbeeld met haakjes #!/usr/bin/perl -w $s = "Frans Goedgebuer"; print "$s\n"; $s =~ s/(w*)\s(\w*)/\2 \1/; print "$s\n\n"; 1.10 De split()-funtie De split() functie is een uitbreiding van de explode() functie. De volgende twee voorbeelden splitsen een datum op een string, waarbij de delen gescheiden worden door een ‘/’ of een ‘-’teken. De opgesplitste gegevens worden daarna afgebeeld. #!/usr/bin/perl -w $s = "25-12-2001"; print "$s\n"; ($dag,$maand,$jaar) = split(/[\/-]/,$s); print "dag: $dag\n"; print "maand: $maand\n"; print "jaar: $jaar\n\n"; en #!/usr/bin/perl -w $s = "25/12/2001"; print "$s\n"; ($dag,$maand,$jaar) = split(/[\/-]/,$s); print "dag: $dag\n"; print "maand: $maand\n"; print "jaar: $jaar\n\n"; Het volgende script toont de werking van de split() functie die gelijkwaardig is met de explode() functie. Merk op dat de er her en der storende spaties staan. #!/usr/bin/perl -w $s = "Jan; Piet; Leo;Els; Tamara ; Stef ;Isabel; Johan"; print "$s\n"; @res = split(/;/,$s); foreach (@res) { print; print "-\n"; } Een string opsplitsen en spaties opruimen is een ‘makkie’ voor reguliere uitdrukkingen: #!/usr/bin/perl -w $s = "Jan; Piet; Leo;Els; Tamara ; Stef ;Isabel; Johan"; print "\n$s\n"; @res = split(/ *; */,$s); foreach (@res) { print; print "-\n"; } Met de join() functie kunnen we een array terug omvormen naar een string: #!/usr/bin/perl -w $s = "Jan; Piet; Leo;Els; Tamara ; Stef ;Isabel; Johan"; Webapplicaties Reguliere uitdrukkingen in Perl print "\n$s\n"; $s = join(";",split(/ *; */,$s)); print "$s\n"; 1.11 De multi-line optie Als de string die we bewerken new-lines bevat, dan verwijzen de Anchoring Patterns, ‘^’ en ‘$’ naar het begin en het einde van de string. Dit is soms niet gewenst. Mits het gebruik van de schakeloptie m zullen deze tekens verwijzen naar het begin en het einde van iedere lijn in deze string (mits het bijkomend gebruik van de schakeloptie g natuurlijk!). #!/usr/bin/perl -w $s="Jan Slaats\nEls De Muer\nMark Bijl\n"; $s =~ s/^/<br>/g; print $s."\n"; $s="Jan Slaats\nEls De Muer\nMark Bijl\n"; $s =~ s/^/<br>/mg; print $s."\n"; $s="Jan Slaats\nEls De Muer\nMark Bijl\n"; $s =~ s/$/<br>/g; print $s."\n"; $s="Jan Slaats\nEls De Muer\nMark Bijl\n"; $s =~ s/$/<br>/mg; print $s."\n"; Webapplicaties Reguliere uitdrukkingen in Perl 2. REGULAR EXPRESSIONS TOEGEPAST IN ANDERE OMGEVINGEN 2.1 Regular Expressions in Javascript Je kan reguliere uitdrukking in javascript op twee manieren bereiken: Door een methode van het sting object toe te passen op een reguliere uitdrukking. Door een methode van het RegExp object toe te passen op een string. 2.1.1 String methods for pattern matching We maken onderscheid tussen 4 methodes: search(), replace(), match(), split(). De methode heeft telkens een reguliere uitdrukking als argument. <script language=Javascript> document.write("<H1>String methods for Pattern Matching</H1>"); document.write("<H2>Search</H2>"); val = "Yoo de mannen".search(/yoo/i); if (val >= 0) document.write("Yoo staat er in, startpositie: "+val); else document.write("Yoo staat er niet in "+val); document.write("<H2>Replace</H2>"); text = "De boze wolf leidde het kleine meisje diep in het grote bos" document.write(text+"<br>"); text = text.replace(/e/g,"E"); document.write(text+"<br>"); document.write("<H2>Match</H2>"); res = "7 plus 12 is gelijk aan 19".match(/\d+/g) for (val in res) { document.write("idx: "+val+" --> "+res[val]+"<br>"); } document.write("<H2>Split</H2>"); res = "10; 18; 45;65; 78 ; 963; 54".split(/\s*;\s*/) for (val in res) { document.write("idx: "+val+" --> "+res[val]+"<br>"); } </script > 2.1.2 RegExp methods for pattern matching We passen de methode test() en exec() toe op de string die we willen onderzoek. <script language=Javascript> document.write("<H1>Het RegExp Object</H1>"); document.write("<H2>Test</H2>"); var pattern = /java/i; if (pattern.test("Javascript")) { document.write(res); } else { document.write(res); } document.write("<H2>Exec</H2>"); var pattern = /java/i; Webapplicaties Reguliere uitdrukkingen in Perl res = pattern.exec("This is Javascript"); for (val in res) { document.write("idx: "+val+" --> "+res[val]+"<br>"); } document.write("<br>Of nog:<br><br>"); document.write("0: " + res[0]+"<br>"); document.write("index: " + res.index+"<br>"); document.write("input: " + res.input+"<br>"); document.write("<H2>Exec en Globaal zoeken</H2>"); var pattern = /java/gi; while (res = pattern.exec("This is Javascript Java Java Java Java")) { for (val in res) { document.write("idx: "+val+" --> "+res[val]+"<br>"); } } </script> 2.1.3 Een praktisch voorbeeld <SCRIPT language=JavaScript><!-function Test_Form(Formulier) { if (!(Formulier.linkadres.value.match(/\s*http:\/\/|^\s*$/))) { alert("Be sure to include http:// in hyperlinks for Field linkadres"); Formulier.linkadres.focus(); return (false); } return (true); } //--> </SCRIPT> <form onsubmit="return Test_Form(this)" name=Formulier> linkadres</td><td><input size=65 maxlength=150 type=text name=linkadres value="http://"><BR> <input type="submit" value="Update this record"> </form> 2.2 Regular Expressions in php Er bestaan 2 groepen van regulier uitdrukking onder php: perl- en posix-compatible. De perlcompatible reguliere uitdrukkingen herken je gemakkelijk aan de afbakening: / /. Hieronder een paar voorbeelden van posix-compatible RE’s in php: <h1>ereg</h1> <? $date = "2000-12-31"; if (ereg ("([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})", $date, $regs)) { echo "$regs[3].$regs[2].$regs[1]<br>"; } else { echo "Invalid date format: $date<br>"; } $date = "2001-8-13"; if (ereg ("([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})", $date, $regs)) { echo "$regs[3].$regs[2].$regs[1]"; } else { echo "Invalid date format: $date"; } ?> <h1>eregi</h1> <? $str = "Els Vandenabeele"; if (ereg ("(^[a-z]+) ", $str, $regs)) { echo "$regs[1]<br>"; } else { Webapplicaties Reguliere uitdrukkingen in Perl echo "Geen geldige naam<br>"; } $str = "Els Vandenabeele"; if (eregi ("(^[a-z]+) ", $str, $regs)) { echo "$regs[1]<br>"; } ?> <h1>split</h1> <? $date = "04/30/1973"; // Delimiters may be slash, dot, or hyphen list ($month, $day, $year) = split ('[/.-]', $date); echo "Month: $month; Day: $day; Year: $year<br>\n"; ?> 2.3 Regular Expressions in Asp/Vbscript <% Dim regEx, keyword Keyword = "een§+twee§+drie§+vier§+vijf" Set regEx = New RegExp regEx.Pattern = "§+" regEx.IgnoreCase = True regEx.Global = True response.write regEx.Replace(Keyword, ",") %> 2.4 Regular Expressions in … (zie luc :-D ) Mvg, Rik Bradt