Recover from microbel
This commit is contained in:
34
README.md
Normal file
34
README.md
Normal file
@ -0,0 +1,34 @@
|
||||
# Kurs i Perl og regex
|
||||
|
||||
## Perl-kurs
|
||||
|
||||
| | |
|
||||
|-------|-----------------------------------------------------------------------------------------------|
|
||||
| Tid: | Torsdag 7. september, fra 18:00 til 20:00 |
|
||||
| Sted: | Auditorium R4, Realfagsbygget |
|
||||
| Pris: | Kr 50 for ikke-medlemmer, gratis for medlemmer og ITEA-ansatte (PVV-medlemsskap koster kr 42) |
|
||||
|
||||
|
||||
PVV arrangerer kurs i programmeringsspråket Perl. Kurset er beregnet for folk som ikke har prøvd Perl før, men kan være nyttig for andre også. Vi fokuserer på hvordan man kan lage enkle script, og på å gi et grunnlag for å lære seg mer selv.
|
||||
|
||||
Kurset forutsetter litt programmeringserfaring, på nivå med if-setninger, løkker og metodekall.
|
||||
|
||||
Kursholder: Knut Auvor Grythe
|
||||
|
||||
### Forrige Perl-kurs
|
||||
|
||||
[Hjemmesiden til perl-kurset som var 2004-10-28](https://git.pvv.ntnu.no/Kurs/2004-perl). Her finner du foiler.
|
||||
|
||||
## Regex-kurs
|
||||
|
||||
| | |
|
||||
|-------|-----------------------------------------------------------------------------------------------|
|
||||
| Tid: | Torsdag 21. september, fra 18:00 til 20:00 |
|
||||
| Sted: | Auditorium R4, Realfagsbygget |
|
||||
| Pris: | Kr 50 for ikke-medlemmer, gratis for medlemmer og ITEA-ansatte (PVV-medlemsskap koster kr 42) |
|
||||
|
||||
PVV arrangerer kurs i Regex, med hovedfokus på implementasjonen til Perl. Kurset tar for seg grunnleggende til middels avansert syntaks. Dette er et ypperlig kurs for alle som er interessert i å gjenkjenne eller manipulere tekst, enten i Perl eller språk med lignende regex-syntaks (med andre ord de fleste programmeringsspråk). Kurset gir også bedre forutsetninger for å forstå regulære uttrykk-pensum i faget TMA4140 Diskret matematikk.
|
||||
|
||||
Kurset forutsetter ingen forkunnskaper.
|
||||
|
||||
Kursholder: Knut Auvor Grythe
|
BIN
regex-kurs.pdf
Normal file
BIN
regex-kurs.pdf
Normal file
Binary file not shown.
761
regex-kurs.tex
Normal file
761
regex-kurs.tex
Normal file
@ -0,0 +1,761 @@
|
||||
\documentclass[screen]{beamer}
|
||||
|
||||
\usepackage[T1]{fontenc}
|
||||
\usepackage[latin1]{inputenc}
|
||||
|
||||
\usepackage{beamerthemesplit}
|
||||
|
||||
\parindent=0pt
|
||||
\parskip=0.5\baselineskip
|
||||
|
||||
\title{Regex i Perl}
|
||||
\author{Knut Auvor Grythe}
|
||||
\date{\today}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\frame{\titlepage}
|
||||
|
||||
%\section[Innhold]{}
|
||||
%\frame{\tableofcontents}
|
||||
|
||||
\section{Introduksjon}
|
||||
\subsection{Litt om regex}
|
||||
\frame
|
||||
{
|
||||
\frametitle{Hva er Regex?}
|
||||
|
||||
\begin{itemize}
|
||||
\item Forkortelse for ``Regular Expression'' (``regul<75>rt uttrykk'' p<> norsk).
|
||||
\item En kjapp og grei m<>te <20> gjenkjenne enkle tekst-strukturer p<>.
|
||||
\item Velegnet for <20> gjenkjenne eller modifisere tekst p<> et gitt format.
|
||||
\item Veldig kompakt syntaks, og dermed lite <20> skrive.
|
||||
\item Kan brukes i de fleste programmeringsspr<70>k (men har ofte litt varierende syntaks)
|
||||
\end{itemize}
|
||||
}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Hvordan ser en regex ut?}
|
||||
|
||||
\begin{itemize}
|
||||
\item En regex er i utgangspunktet bare en tekststreng, der noen f<> av tegnene har en spesiell betydning.
|
||||
\item I en del spr<70>k (for eksempel Perl) skrives regexer med en skr<6B>strek f<>r og etter.
|
||||
\item Denne regexen gjenkjenner teksten ``banan'': /banan/
|
||||
\end{itemize}
|
||||
}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Hva gj<67>r den egentlig?}
|
||||
|
||||
\begin{itemize}
|
||||
\item En regex g<>r gjennom teksten \textit{fra venstre til h<>yre}, helt til den finner et treff.
|
||||
\item En regex er gr<67>dig. Om to ulike treff begynner p<> samme sted i teksten, vil den alltid ta det lengste.
|
||||
\item Hva som skjer n<>r regexen matcher noe avhenger av hvordan den er brukt.
|
||||
\end{itemize}
|
||||
}
|
||||
|
||||
\subsection{Praktisk bruk}
|
||||
\frame
|
||||
{
|
||||
\frametitle{Bruksomr<EFBFBD>der i Perl}
|
||||
|
||||
Tre vanlige bruksomr<6D>der for regex i perl er matching, substitusjon og
|
||||
splitting. Det finnes ogs<67> andre bruksomr<6D>der, men da er det i praksis
|
||||
matching som utf<74>res.
|
||||
|
||||
\begin{block}{Matching}
|
||||
if (\$var =\~{} /banan/) \{
|
||||
do\_stuff();
|
||||
\}
|
||||
\end{block}
|
||||
|
||||
\begin{block}{Substitusjon}
|
||||
\$var =\~{} s/banan/eple/;
|
||||
\end{block}
|
||||
|
||||
\begin{block}{Splitting}
|
||||
my @array = split(/a/, ``banan'');
|
||||
\end{block}
|
||||
}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Hvordan bruke andre tegn enn //}
|
||||
|
||||
Selv om det er standard <20> skrive regexen inni //, er det fullt lovlig <20>
|
||||
bruke andre tegn i stedet. Dette er kjekt om du skal matche et pattern med
|
||||
mange /-er i, og ikke har lyst til <20> escape alle sammen.
|
||||
|
||||
For at Perl skal kjenne igjen matching m<> man skrive en ``m'' foran
|
||||
uttrykket, dersom man bruker noe annet enn //.
|
||||
|
||||
Det er ganske vanlig <20> bruke komma eller kolon som tegn.
|
||||
|
||||
\begin{block}{Matching}
|
||||
if (\$var =\~{} m,banan,) \{
|
||||
do\_stuff();
|
||||
\}
|
||||
\end{block}
|
||||
|
||||
\begin{block}{Substitusjon}
|
||||
\$var =\~{} s,banan,eple,;
|
||||
\end{block}
|
||||
|
||||
}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Modifikatorer}
|
||||
Modifikatorer er ting du kan skrive bak uttrykket ditt for <20> f<> det til <20>
|
||||
oppf<70>re seg litt annerledes. Vi konsentrerer oss om de to viktigste, /g og /i.
|
||||
|
||||
Modifikatorer brukes ved <20> plassere dem rett bak siste / i utrykket.
|
||||
|
||||
\begin{block}{Eksempler}
|
||||
\begin{tabular}{ll}
|
||||
\textbf{/abcd/i} & et matche-uttrykk med /i.\\
|
||||
\textbf{s/abcd/blarb/g} & et substitusjons-uttrykk med /g.\\
|
||||
\textbf{s/abcd/blarb/ig} & et substitusjons-uttrykk med b<>de /g og /i.\\
|
||||
\end{tabular}
|
||||
\end{block}
|
||||
}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Modifikatorer - Hva de gj<67>r}
|
||||
|
||||
N<> som vi vet hvordan vi slenger p<> en modifikator kan vi kanskje f<> vite
|
||||
hva de gj<67>r ogs<67> :-)
|
||||
|
||||
\textbf{/i} gj<67>r at uttrykket ikke skiller p<> store og sm<73> bokstaver
|
||||
(case-insensitive). Litt tregere enn <20> bare skrive inn store og sm<73>
|
||||
bokstaver manuelt, siden den f<>lger gjeldende locale, men neppe noe problem
|
||||
i praksis.
|
||||
|
||||
\textbf{/g} brukes kun i substitusjon, og st<73>r for ``global''. Vanligvis
|
||||
vil substitusjonen bare bytte ut f<>rste treff, men med denne vil den bytte
|
||||
ut \textit{alle} treff.
|
||||
}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Kommandolinje-testing av matche-uttrykk (``grepping'')}
|
||||
|
||||
\begin{block}{Perl}
|
||||
echo "vi liker bananer" | perl -ne 'print if /banan/'
|
||||
\end{block}
|
||||
|
||||
\begin{block}{Andre spr<70>k}
|
||||
echo "vi liker bananer" | grep 'banan'\newline
|
||||
echo "vi liker bananer" | sed -e '/banan/p' -e 'd'\newline
|
||||
echo "vi liker bananer" | awk '/banan/ \{print\}'
|
||||
\end{block}
|
||||
|
||||
}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Kommandolinje-testing av substitusjons-uttrykk (``sedding'')}
|
||||
|
||||
\begin{block}{Perl}
|
||||
echo "vi liker bananer" | perl -pe 's/banan/rosin/'
|
||||
\end{block}
|
||||
|
||||
\begin{block}{Andre spr<70>k}
|
||||
echo "vi liker bananer" | sed 's/banan/rosin/'\newline
|
||||
echo "vi liker bananer" | awk '\{sub(/banan/, "rosin"); print\}'
|
||||
\end{block}
|
||||
|
||||
}
|
||||
|
||||
\section{Oversikt over syntaks}
|
||||
\subsection{Spesielle tegn og hva de gj<67>r}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{<EFBFBD> matche en helt vanlig tekst-streng}
|
||||
|
||||
Om du skal matche en helt vanlig tekst-streng, kan du bare skrive den rett
|
||||
ut, som for eksempel /banan/ som vi har sett f<>r.
|
||||
|
||||
\begin{block}{NB!}
|
||||
Husk imidlertid at enkelte tegn har spesiell betydning, og disse m<> escapes
|
||||
om du vil ha selve tegnet. Et eksempel p<> dette er punktum, som kan matches
|
||||
med /$\backslash$./.
|
||||
|
||||
Den st<73>rste forskjellen p<> de ulike regex-dialektene er hva som skal
|
||||
escapes. En del spr<70>k tolker alt som tekst, og bruker spesialbetydningen
|
||||
n<>r du escaper i stedet. Hva andre spr<70>k gj<67>r er imidlertid litt utenfor
|
||||
skopet til kurset.
|
||||
\end{block}
|
||||
}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Liste over magiske tegn(-sekvenser)}
|
||||
|
||||
\begin{tabular}{ll}
|
||||
$\backslash$ & Quote the next metacharacter\\
|
||||
. & Match any character (except newline)\\
|
||||
* & Match 0 or more times\\
|
||||
+ & Match 1 or more times\\
|
||||
? & Match 1 or 0 times\\
|
||||
\{n\} & Match exactly n times\\
|
||||
\{n,\} & Match at least n times\\
|
||||
\{n,m\} & Match at least n but not more than m times\\
|
||||
\^{} & Match the beginning of the line\\
|
||||
\$ & Match the end of the line (or before newline at the end)\\
|
||||
| & Alternation\\
|
||||
() & Grouping\\
|
||||
$[ ]$ & Character class\\
|
||||
\end{tabular}
|
||||
}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Tegnet . (punktum)}
|
||||
|
||||
. (punktum) matcher et vilk<6C>rlig tegn.
|
||||
|
||||
\begin{block}{Eksempel}
|
||||
\textbf{/bl.pp/} matcher ``blipp'', ``blapp'', ``blupp'' og s<> videre.
|
||||
\end{block}
|
||||
|
||||
\begin{block}{NB:}
|
||||
``Vilk<6C>rlige tegn'' inneb<65>rer ogs<67> whitespace, men per default ikke linjeskift (kan endres med en modifier vi snakker om senere).
|
||||
\end{block}
|
||||
}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Tegnet * (stjerne)}
|
||||
|
||||
* (stjerne) sier at forrige tegn skal matches 0 eller flere ganger.
|
||||
|
||||
\begin{block}{Eksempel 1}
|
||||
\textbf{/bla*pp/} matcher ``blpp'', ``blapp'', ``blaapp'', ``blaaapp'' og s<> videre.
|
||||
\end{block}
|
||||
|
||||
\begin{block}{Eksempel 2}
|
||||
\textbf{/bl.*pp/} matcher alt i Eksempel 1, samt f.eks. ``blupp'', ``bl<62>b<EFBFBD>rkopp'', ``bl<62> muggsopp'' og s<> videre.
|
||||
\end{block}
|
||||
}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Tegnet + (pluss)}
|
||||
|
||||
+ (pluss) fungerer akkurat som * (stjerne), bortsett fra at det er ``1 eller flere'' i stedet for ``0 eller flere''.
|
||||
|
||||
\begin{block}{Eksempel}
|
||||
\textbf{/bla+pp/} matcher ``blapp'', ``blaapp'', ``blaaapp'' og s<> videre, men ikke ``blpp'' (som \textbf{/bla*pp/} ville matchet).
|
||||
\end{block}
|
||||
}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Tegnet ? (sp<73>rsm<73>lstegn)}
|
||||
|
||||
? (sp<73>rsm<73>lstegn) sier at forrige tegn skal matches ``0 eller 1'' ganger.
|
||||
|
||||
\begin{block}{Eksempel}
|
||||
\textbf{/fisk?/} matcher ``fisk'' og ``fis'', og ingenting annet.
|
||||
\end{block}
|
||||
}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Tegnene \{ og \} (kr<6B>llparenteser)}
|
||||
|
||||
\{ og \} brukes for <20> gi et egendefinert intervall over hvor mange ganger forrige tegn skal matches.
|
||||
|
||||
\begin{block}{Eksempler}
|
||||
\textbf{/fi\{3\}sk/} matcher ``fiiisk''.\newline
|
||||
\textbf{/fi\{2,3\}sk/} matcher ``fiisk'' og ``fiiisk''.\newline
|
||||
\textbf{/fi\{2,\}sk/} matcher ``fiisk'', ``fiiisk'', ``fiiiisk'' og s<> videre.
|
||||
\end{block}
|
||||
|
||||
\begin{block}{NB!}
|
||||
F<>rste argument er ikke valgfritt! \textbf{/fi\{,3\}sk/} matcher faktisk bare ``fi\{,3\}sk''.
|
||||
\end{block}
|
||||
}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Sammenhengen mellom kvantifikatorene)}
|
||||
|
||||
\begin{tabular}{|l|l|}\hline
|
||||
\textbf{Tegn} & \textbf{Kr<EFBFBD>llparentes-uttrykk} \\ \hline
|
||||
* & \{0,\} \\
|
||||
+ & \{1,\} \\
|
||||
? & \{0,1\} \\ \hline
|
||||
\end{tabular}
|
||||
|
||||
Du kan med andre ord bruke kun \{ og \} om du vil, men ingen gj<67>r det i praksis.
|
||||
}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Tegnet \^{} og \$ (hatt og dollar)}
|
||||
|
||||
\^{} og \$ matcher henholdsvis ``start of line'' og ``end of line''.
|
||||
|
||||
Det vil alts<74> si endene p<> variablene. Dersom det siste tegnet i variabelen
|
||||
er et linjeskift, matcher den ogs<67> rett f<>r linjeskiftet.
|
||||
|
||||
\begin{block}{Eksempler}
|
||||
\textbf{/\^{}banan/} matcher ``banankompott'', men ikke ``stor banan''.\newline
|
||||
\textbf{/banan\$/} matcher ``stor banan'', men ikke ``banankompott''.\newline
|
||||
\textbf{/\^{}banan\$/} matcher kun ``banan'' eller ``banan$\backslash$n''.
|
||||
\end{block}
|
||||
}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Tegnet | (pipe)}
|
||||
|
||||
| (pipe) betyr ``eller'', og er sikkert velkjent fra boolsk algebra.
|
||||
Det kan settes mellom to eller flere alternativer for match.
|
||||
|
||||
\begin{block}{Eksempel 1}
|
||||
\textbf{/banan|eple/} matcher b<>de ``banan'' og ``eple'' (og strenger som inneholder en eller flere av dem av dem).
|
||||
\end{block}
|
||||
|
||||
\begin{block}{Eksempel 2}
|
||||
\textbf{/banan|eple|p<>re/} matcher det samme som Eksempel 1, pluss ``p<>re''.
|
||||
\end{block}
|
||||
}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Tegnene ``('' og ``)'' (parenteser)}
|
||||
|
||||
Parenteser brukes til <20> gruppere, mye p<> samme m<>ten som vi er vant til fra
|
||||
boolsk algebra.
|
||||
|
||||
De brukes ogs<67> til litt annet sm<73>tteri, som vi skal se p<> snart.
|
||||
|
||||
\begin{block}{Eksempel}
|
||||
\textbf{/\^{}(banan|sviske)kompott\$/} matcher ``banankompott'' og ``sviskekompott''.
|
||||
\end{block}
|
||||
}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Tegnene [ og ] (firkantparenteser)}
|
||||
|
||||
Firkantparenteser brukes n<>r det er flere alternativer til et tegn.
|
||||
Tegnene skrives rett og slett etter hverandre inni firkantparentesene.
|
||||
|
||||
Firkantparenteser er egentlig et kapittel for seg, og kommer mer utfyllende senere.
|
||||
|
||||
\begin{block}{Eksempel}
|
||||
\textbf{/bl$[$aui$]$pp/} matcher ``blapp'', ``blupp'' eller ``blipp''.
|
||||
\end{block}
|
||||
}
|
||||
|
||||
\subsection{Mer om gruppering}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Mer om parenteser}
|
||||
|
||||
Som vi s<> for ikke s<> lenge siden, brukes parenteser til <20> gruppere ting
|
||||
med. Vi s<> eksempelet \textbf{/\^{}(banan|sviske)kompott\$/}, der
|
||||
parenteser brukes til <20> avgrense skopet til variable.
|
||||
|
||||
Parenteser kan imidlertid ogs<67> brukes til <20> hente ut en substreng av det
|
||||
som ble matchet, og det kan vi bruke til mye rart.
|
||||
}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Variablene \$1, \$2, \$3, etc. (1)}
|
||||
|
||||
N<>r et uttrykk med parenteser i matcher, blir innholdet i parentesene lagt
|
||||
i spesielle variable, kalt ``tilbakereferanser''. Den f<>rste p<>begynte
|
||||
parentesen blir lagt i \$1, den neste i \$2, og s<> videre.
|
||||
|
||||
Merk at disse variablene m<> brukes med en gang, siden de forsvinner s<> fort
|
||||
du gj<67>r en ny regex-matching lenger nede i koden. Ta en kopi!
|
||||
}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Variablene \$1, \$2, \$3, etc. (2)}
|
||||
|
||||
Dette eksempelet plasserer ``en'' i \$a og ``to'' i \$b dersom uttrykket
|
||||
matcher (og det gj<67>r det).
|
||||
|
||||
\begin{block}{Eksempel}
|
||||
my \$var = "en to";\newline
|
||||
my \$a;\newline
|
||||
my \$b;
|
||||
|
||||
if (\$var =\~{} /(.*) (.*)/) \{\newline
|
||||
\hspace*{1em} \$a = \$1;\newline
|
||||
\hspace*{1em} \$b = \$2;\newline
|
||||
\}
|
||||
\end{block}
|
||||
|
||||
}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Direkte uthenting av tilbakereferanser}
|
||||
|
||||
Om du kaller en matching i array-kontekst returneres alle
|
||||
tilbakereferansene som en array.
|
||||
|
||||
Ulempen med denne metoden er at du m<> unders<72>ke verdiene etterp<72> for <20> f<>
|
||||
vite om det matchet eller ikke, og det blir ikke like pent i mine <20>yne.
|
||||
Notasjonen er heller ikke s<> intuitiv, sp<73>r du meg.
|
||||
|
||||
Jeg ser sjelden denne konstruksjonen i bruk i praksis.
|
||||
|
||||
\begin{block}{Eksempel}
|
||||
my \$var = "en to";\newline
|
||||
my (\$a, \$b) = \$var =\~{} /(.*) (.*)/;
|
||||
\end{block}
|
||||
}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Bruk av tilbakereferanser i substitusjons-uttrykk}
|
||||
|
||||
Du kan ogs<67> bruke \$1 med venner i substitusjoner.
|
||||
|
||||
\begin{block}{Eksempel}
|
||||
\# Dette bytter om p<> ``en'' og ``to''.\newline
|
||||
my \$var = ''en to'';\newline
|
||||
\$var =\~{} s/(.*) (.*)/\$2 \$1/;
|
||||
\end{block}
|
||||
|
||||
\begin{block}{PS:}
|
||||
En del andre spr<70>k, som f.eks. sed og vim, bruker $\backslash$1 i stedet
|
||||
for \$1 og s<> videre.
|
||||
\end{block}
|
||||
}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Bruk av tilbakereferanser inne i selve patternet}
|
||||
|
||||
Om du vil, kan du ogs<67> bruke tilbakereferanser til en tidligere del av
|
||||
patternet lenger ute i regexen. Dette kan for eksempel v<>re kjekt om du
|
||||
skal matche en serie av like tegn, men det er mer enn ett alternativ for
|
||||
hvilket tegn det er.
|
||||
|
||||
N<>r du gj<67>r tilbakereferanser inne i selve patternet, m<> du bruke
|
||||
$\backslash$1 i stedet for \$1 og s<> videre. \$1 og lignende vil
|
||||
\textit{ikke} virke! De er nemlig ikke definert enn<6E>.
|
||||
|
||||
\begin{block}{Eksempel: Fjerning av trippelkonsonanter}
|
||||
my \$var = ''busssj<73>f<EFBFBD>r'';\newline
|
||||
\$var =\~{} s/(.)$\backslash$1+/\$1\$1/g;
|
||||
\end{block}
|
||||
}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Viktig bruksomr<6D>de: Tainting}
|
||||
|
||||
Tainted mode er en feature i Perl som tvinger deg til <20> sjekke inputen din
|
||||
til scripts. Det er et nyttig verkt<6B>y for <20> unng<6E> lite kledelige
|
||||
sikkerhetshull i webapplikasjoner, for eksempel.
|
||||
|
||||
Tainted mode virker slik at det eneste du f<>r lov <20> bruke innleste (ergo
|
||||
potensielt skumle) variabler til, er <20> kj<6B>re regex-matching p<> dem. S<> kan
|
||||
du hente ut \$1 med venner derfra, og bruke dem.
|
||||
|
||||
Tainted mode sl<73>s p<> med opsjonen -T bak perl-programmet.
|
||||
}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Hvordan gruppere uten at innholdet huskes}
|
||||
|
||||
Om du <20>nsker <20> bruke parenteser til gruppering, men \textit{ikke} <20>nsker <20>
|
||||
bruke innholdet i parentesen etterp<72>, kan du bruke ``?:'' f<>rst i
|
||||
parentesen.
|
||||
|
||||
Dette er spesielt nyttig i split(), men ogs<67> greit om du har masse
|
||||
parenteser du vil huske, men s<> plutselig noen du ikke vil huske midt inni.
|
||||
Det sparer ogs<67> bittelitt minne, men det er mindre viktig.
|
||||
|
||||
\begin{block}{Eksempel}
|
||||
\# returnerer (``b'', ``a'', ``n'', ``a'', ``n'', ``e'', ``r'')\newline
|
||||
my @a = split(/(a|e)/, "bananer");
|
||||
|
||||
\# returnerer (``b'', ``n'', ``n'', ``r'')\newline
|
||||
my @b = split(/(?:a|e)/, "bananer");
|
||||
\end{block}
|
||||
}
|
||||
|
||||
\subsection{Mer om tegnklasser}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Et gjensyn med $[$ og $]$}
|
||||
|
||||
For en stund siden snakket vi s<> vidt om $[$ og $]$, som brukes for <20>
|
||||
definere en klasse av tegn. De skal vi snakke litt mer om n<>.
|
||||
|
||||
La oss f<>rst huske at en serie med tegn i firkantparenteser betyr at vi
|
||||
matcher ett av tegnene i firkantparentesen en gang.
|
||||
|
||||
\begin{block}{Eksempel}
|
||||
\textbf{/$[$abc$]$/} matcher ett tegn, som kan v<>re enten ``a'', ``b''
|
||||
eller ``c''.
|
||||
\end{block}
|
||||
}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Matching av fleksibelt antall tegn med tegnklasse}
|
||||
|
||||
Skal vi matche et annet antall tegn enn n<>yaktig ett, m<> vi (som vanlig)
|
||||
bruke en kvantifikator som f.eks. *, +, ? eller \{m,n\}.
|
||||
|
||||
\begin{block}{Eksempel}
|
||||
\textbf{/$[$abc$]$+/} matcher ett eller flere tegn, som kan v<>re enten
|
||||
``a'', ``b'' eller ``c''.
|
||||
\end{block}
|
||||
}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Tegnsekvenser}
|
||||
|
||||
Siden det er litt tiltak <20> skrive tegnklasser som for eksempel
|
||||
\textbf{$[$0123456789$]$}, \textbf{$[$abcdef$]$} og s<>nt, har man mulighet
|
||||
for <20> angi intervaller. Dette gj<67>res med bindestrek.
|
||||
|
||||
\begin{tabular}{|l|l|}\hline
|
||||
\textbf{Sekvens} & \textbf{Tilsvarer} \\ \hline
|
||||
\textbf{$[$0-9$]$} & \textbf{$[$0123456789$]$} \\
|
||||
\textbf{$[$a-f$]$} & \textbf{$[$abcdef$]$} \\
|
||||
\textbf{$[$0-9a-f$]$} & \textbf{$[$0123456789abcdef$]$} \\
|
||||
\hline
|
||||
\end{tabular}
|
||||
|
||||
\begin{block}{Eksempel}
|
||||
\textbf{/\^{}0x$[$0-9a-fA-F$]$+\$/} matcher et hexadecimalt tall, som for
|
||||
eksempel ``0x1337babe''.
|
||||
\end{block}
|
||||
}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Negasjon}
|
||||
|
||||
Av og til <20>nsker du <20> matche alt unntatt visse tegn, som for eksempel alt
|
||||
unntatt kolon. For <20> gj<67>re dette kan du bruke en negert tegnklasse. Dette
|
||||
gj<67>res ved <20> sette tegnet \^{} (hatt) fremst i tegnklassen.
|
||||
|
||||
Det stemmer, hatt betyr noe helt annet inni en tegnklasse enn den betyr
|
||||
utenfor. Litt forvirrende i starten, men det g<>r fort over.
|
||||
|
||||
\begin{block}{Eksempel}
|
||||
\textbf{/\^{}($[$\^{}:$]$*)/} matcher fra starten av strengen til f<>rste
|
||||
kolon (eller slutten av strengen, om det ikke finnes noe kolon i den) og
|
||||
legger resultatet i \$1.
|
||||
\end{block}
|
||||
}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Escaping av spesielle tegn i tegnklasser}
|
||||
|
||||
Siden \^{} (hatt), - (bindestrek) og $]$ har spesiell betydning i en
|
||||
tegnklasse ($]$ avslutter klassen), m<> man escape dem om man vil ha et
|
||||
bokstavelig tegn.
|
||||
|
||||
Dette kan gj<67>res enten ved <20> escape dem med backslash, eller ved <20> plassere
|
||||
dem spesielle steder i tegnklassen. I praksis brukes ofte spesiell
|
||||
plassering, siden dette er vanlig i andre regex-implementasjoner.
|
||||
|
||||
\begin{tabular}{|l|l|} \hline
|
||||
\textbf{Tegn} & \textbf{Plassering for <20> escape} \\ \hline
|
||||
\^{} (hatt) & Et annet sted enn fremst \\
|
||||
- (bindestrek) & Helt bakerst eller helt fremst (bak eventuell hatt) \\
|
||||
$]$ & Helt fremst (bak eventuell hatt) \\
|
||||
\hline
|
||||
\end{tabular}
|
||||
}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Ferdigdefinerte tegnklasser}
|
||||
|
||||
Perl har ogs<67> en del ferdigdefinerte tegnklasser. Disse kan brukes enten som byggestener i egendefinerte tegnklasser, eller for seg selv.
|
||||
|
||||
Eksemplene nedenfor benytter $\backslash$w, som matcher tegn som kan v<>re i
|
||||
ord (det vil si bokstaver, tall og \_ (underscore)).
|
||||
|
||||
\begin{block}{Eksempler}
|
||||
\textbf{/($\backslash$w+)/} henter ut det f<>rste ordet og legger det i \$1.
|
||||
|
||||
\textbf{/($[$$\backslash$w-$]$+)/} gj<67>r som forrige eksempel, men tillater
|
||||
bindestrek i ordet.
|
||||
\end{block}
|
||||
}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Liste over ferdigdefinerte tegnklasser}
|
||||
|
||||
Dette er en liten oversikt over de mest brukte ferdigdefinerte
|
||||
tegnklassene. Det finnes en del flere, men de er ikke like vanlige. Du
|
||||
finner dem i ``perldoc perlre''.
|
||||
|
||||
\begin{tabular}{|l|l|}\hline
|
||||
\textbf{Klasse} & \textbf{betydning} \\ \hline
|
||||
$\backslash$w & Match a "word" character (alphanumeric plus ``\_'')\\
|
||||
$\backslash$W & Match a non-"word" character\\
|
||||
$\backslash$s & Match a whitespace character\\
|
||||
$\backslash$S & Match a non-whitespace character\\
|
||||
$\backslash$d & Match a digit character\\
|
||||
$\backslash$D & Match a non-digit character\\
|
||||
$\backslash$b & Match a word boundary\\
|
||||
\hline
|
||||
\end{tabular}
|
||||
}
|
||||
|
||||
\section{Eksempler og avslutning}
|
||||
|
||||
\subsection{Eksempler}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Eksempel: Strippe HTML}
|
||||
|
||||
Dette eksempelet har dere sikkert sett f<>r, p<> plakaten til kurset. N<> har
|
||||
dere sikkert l<>rt nok til <20> se hva den gj<67>r ogs<67>!
|
||||
|
||||
Merk at om du leser inn en linje om gangen vil ikke denne koden st<73>tte
|
||||
html-tags som g<>r over flere linjer.
|
||||
|
||||
Vi ser at uttrykket matcher en <, s<> innholdet i tagen (ett eller flere
|
||||
tegn som ikke er >, og s<> til slutt >. Substitusjonen er ogs<67> global, s<>
|
||||
alle treffene blir erstattet med en tom streng.
|
||||
|
||||
\begin{block}{Eksempel}
|
||||
\textbf{s/<$[$\^{}>$]$+>//g}
|
||||
\end{block}
|
||||
}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Eksempel: Hente ut linker fra HTML}
|
||||
|
||||
Om du vil hente ut alle linkene i et HTML-dokument, kan du for eksempel
|
||||
matche p<> det som er i hermetegn bak ``href=''.
|
||||
|
||||
\textbf{$\backslash$s*} er med her og der fordi det er valgfritt med mellomrom der.
|
||||
|
||||
\begin{block}{Eksempel}
|
||||
\textbf{/href$\backslash$s*=$\backslash$s*''([\^{}'']+)/i}
|
||||
\end{block}
|
||||
|
||||
\begin{block}{I praktisk bruk}
|
||||
\textbf{perl -ne 'print ''\$1$\backslash$n'' if /href$\backslash$s*=$\backslash$s*''([\^{}'']+)/i' fil.html}
|
||||
\end{block}
|
||||
}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Eksempel: Hente ut flere linker per linje fra HTML}
|
||||
|
||||
Eksempelet p<> forrige slide hadde en begrensning: Det st<73>ttet bare en link
|
||||
per linje. Det er sikkert fullt mulig <20> lage en regex som st<73>tter <20> fiske
|
||||
ut flere, og legge dem i \$1, \$2 og s<> videre, men det blir bare tungvint
|
||||
og ekkelt. I stedet kan vi enten modifisere input-dataene (f.eks. legge inn
|
||||
linjeskift mellom alle HTML-tags) eller kj<6B>re flere matchinger per linje.
|
||||
Vi satser p<> <20> gj<67>re flere matchinger per linje.
|
||||
|
||||
Her har vi samme regex som i stad, men substituerer bort patternet i stedet
|
||||
for <20> matche det. Slik holder vi p<> til det ikke er mer som matcher.
|
||||
|
||||
\begin{block}{Eksempel}
|
||||
\textbf{perl -ne 'print ''\$1$\backslash$n'' while s/href$\backslash$s*=$\backslash$s*''([\^{}'']+)//i' fil.htm}
|
||||
\end{block}
|
||||
}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Eksempel: Matche primtall}
|
||||
|
||||
F<>lgende kode matcher et primtall. Den er vel kanskje ikke kjempe-intuitiv,
|
||||
men virker for sm<73> primtall. For store primtall g<>r den kjapt tom for minne
|
||||
og tryner.
|
||||
|
||||
Dette er for <20>vrig omtrent tregest tenkelige m<>te <20> regne ut om noe er
|
||||
primtall eller ikke, s<> den b<>r kun brukes som kuriositet ;-)
|
||||
|
||||
Den fungerer ved at man f<>rst matcher to eller flere tegn, f<>r man matcher
|
||||
denne sekvensen to eller flere ganger. I praksis bruteforcer man alts<74> om
|
||||
tallet er delelig med noe.
|
||||
|
||||
\begin{block}{Eksempel}
|
||||
perl -e '(1x\$ARGV$[$0$]$) =\~{} /\^{}(..+?)$\backslash$1+\$/ || print ``prime$\backslash$n'''
|
||||
\end{block}
|
||||
}
|
||||
|
||||
\subsection{Avslutning}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Generelle triks}
|
||||
|
||||
N<>r du skriver en regex er det noen f<> triks som gjerne sparer deg for en
|
||||
del hodebry:
|
||||
|
||||
\begin{itemize}
|
||||
\item Gj<47>r den enkel f<>rst, legg p<> s<>rtilfeller etter hvert.
|
||||
\item Test at den gj<67>r det du vil underveis. Det er fort gjort <20> snike inn
|
||||
en skrivefeil som <20>delegger alt.
|
||||
\item Om regexen blir kjempediger og f<>l, stopp og tenk p<> hvorvidt dette
|
||||
egentlig var rett verkt<6B>y <20> bruke. Kanskje du b<>r lage en skikkelig
|
||||
parser i stedet?
|
||||
\item Av og til kan det v<>re kjekt <20> f<>rst matche p<> et grovt pattern,
|
||||
hente ut det som er interessant, og s<> matche videre med en ny regex.
|
||||
\end{itemize}
|
||||
}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Hva er Regex IKKE bra til?}
|
||||
|
||||
N<> som vi har sett at regex gj<67>r det mulig <20> gj<67>re masse flott, er det kanskje en plan <20> se litt p<> hva det \textit{ikke} passer s<> bra til.
|
||||
|
||||
\begin{itemize}
|
||||
\item Regex st<73>tter ikke rekursjon. Dette gj<67>r det h<>pl<70>st <20> matche f.eks.
|
||||
HTML skikkelig, siden vi ikke kan holde styr p<> start- og slutt-tager.
|
||||
\item Om teksten er litt komplisert er det ofte vel s<> greit <20> skrive en
|
||||
skikkelig parser, i stedet for en supergrisete regex.
|
||||
\item Regex er ikke veldig maintainable, spesielt ikke om du overdriver.
|
||||
\end{itemize}
|
||||
}
|
||||
|
||||
\frame
|
||||
{
|
||||
\frametitle{Hvordan l<>re mer?}
|
||||
|
||||
Om du vil l<>re mer, er det selvsagt et triks <20> bruke regex en del. Selv
|
||||
bruker jeg bortimot daglig regex til et eller annet, som regel i
|
||||
forbindelse med sm<73> onelinere jeg bruker for <20> massere tekst. Jeg bruker
|
||||
det ogs<67> mye for <20> gj<67>re s<>k og erstatt i vim (jeg har brukt en del regexer
|
||||
i vim mens jeg skrev disse foilene).
|
||||
|
||||
Om du vil lese mer, er kommandoen ``perldoc perlre'' veldig fin. O'Reilly
|
||||
har ogs<67> noen b<>ker jeg tror er bra, og et par av dem ligger sikkert p<>
|
||||
PVV.
|
||||
|
||||
Har man et obskurt problem er det ogs<67> ofte hjelp <20> f<> p<> IRC, eventuelt p<>
|
||||
mailinglister med nerder p<> (som f.eks. aktive@pvv.ntnu.no).
|
||||
}
|
||||
|
||||
\end{document}
|
Reference in New Issue
Block a user