1. Regular Expressions in Perl

advertisement
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
Download