Regulære uttrykk
Regex En streng som beskriver eller korrelerer til en mengde strenger, dvs. én eller flere. Korrelasjonen bestemmes av mønsteret i denne strengen, som er underlagt regler. Mye brukt i mange programmeringspråk, deriblant C/C++, Perl, Java,…,PHP Stort felt – trenger ikke nødvendigvis kunne alle aspekter for å bruke det
Eksempel 1 Vi vil finne ut som en bruker har tastet inn en gyldig e-post adresse, basert kun på syntaks: ronnyma@math.uio.no kari.bremnes@fara.mexico.com
Eksempel 1 Intuitiv måte å gjøre denne oppgaven på: Lage en løkke som tar for seg strengen Opprette et ”bokholderi”, for eksempel sjekke at den inneholder kun lovlige tegn, en ”@” og bare lovlige tegn, et ”.” og en sekvens av lovlige tegn med to, tre eller fire tegn
Eksempel 1 $str = "ronnyma@uio.no"; for( $i = 0; $i < strlen( $str ); $i++ ) { $sc = $str[ $i ]; if( !check_char( $sc ) ) echo "Invalid character $sc<br>"; } function check_char( $str ) $valid = false; $value = ord( $str ); if( ( $value > 47 && $value < 58 ) || ( $value > 63 && $value < 90 ) || ( $value > 96 && $value < 122 ) || $value != 46 || $value != 95) $valid = true; return $valid;
Eksempel 1 Tungvindt, ressurskrevende og uoversiktlig I tillegg sjekker vi ikke for mønster x antall tegn, og (alternativt) ”.” + x antall tegn så mange ganger vi vil @ Tilslutt: ”.” + 2, 3 eller 4 bokstaver
Konklusjon eks. 1 Det må / burde finnes en bedre måte Det gjør det, heldigvis. Svaret er regulære uttrykk (Regex)
Eksempel 2 ronnyma@math.uio.no Denne ”strengen” følger et mønster, likt det som ble beskrevet for to slider siden En regex-streng som ville korrelere til denne: [a-zA-Z0-9]+(\.[a-zA-Z0-9]+)*@[a-zA-Z0-9]+(\.[a-zA-Z0-9]+)*\.[a-zA-Z]{2,4} Snart vil denne være like selvsagt for deg som 呀, 呀, 祖 母 er for en kineser
Verktøy http://www.roblocher.com/technotes/regexp.aspx Regex-coach for win32 (gratis)
Bruksområder Parse en html-side, f. eks ”låne” aftenposten.no’s valutakurser Hente ut annen info fra en tekstfil Validere input Avansert søkning og erstatting i tekst (jmf. str_replace())
Matche enkelt-tegn . = ett enkelt tegn, bortsett fra []\^$.|?*+() a = a, b = b etc. (0-9) [abc] = a eller b eller c [^abc] = alt annet enn a,b og/eller c \tegn = escape \d = numerisk tegn \s = whitespace (mellomrom, linjeskift etc)
Eksempel ”php” matches av: Dette er en setning IPV4: ^php, [ph]+, php$ og ^php$, ., .{3}, .+ Dette er en setning [setnig]+ , $setning Ikke: ^setning (hvorfor kommer senere) IPV4: (\d{1,3}\.){3}(\d{1,3})
Kvantifikatorer ? Kun en tillatt, men ikke påkrevet * Mange tillatt, men ikke påkrevet + En påkrevet, men mange tillatt {a,b} a påkrevet, b tillatt {a} a påkrevet
Eksempel Et ord på minst 3, maks 10 bokstaver .{3,10} Et ord på 5 bokstaver, som består av tegnene n, o, r, g og e [norge]{5}, [groen]{5} matcher norge, groen etc c+ minst én c, men sa mange man vil c* så mange man vil, inkludert 0 c? en eller ingen
Posisjoner ^ Posisjonen ved linjestart $ Posisjonen ved linjeslutt \< Posisjonen ved ord-start \> Posisjonen ved ord-slutt
Eksempel Dette er en streng ^en \<en streng$ en$
Annet | or, dvs. gruppering av flere uttrykk (..) Gruppering for kvanitifikatorer (bla.a)
Eksempel (\d{10,15}) | (\d{3,5}) <\s*body\s*> <\s*img\s+src\s*=\s*\”.+\”\s> <h[123456]> <h[1-6]> [1234567890a-fA-F]
En liten oppgave Hvorfor får vi ikke treff her: q[^u] på Quantas og Iraq
En til På engelsk skrives farge slik: color og colour Skulle vi da søke etter dette ordet, hvordan er det smart å gå frem? Først color, så colour? Eller: col[ou]{2}r? -> også coluor Bedre med col(o|ou)r
Mer… Vi kan skrive 1000000, 1 000 000 eller ”én million” (revisorer skriver 15 tusen i stedet for 15 000) Lag et regex som matcher!
Tidsangivelse Klokken skrives typisk slik: (i USA) 9:17 am, 12:30 pm [0-9]?[0-9]:[0-9] [0-9] (am|pm) plukker opp de to foregående, men også 99:99 pm Riktig er: (1[012]|[1-9]):[0-5][0-9] (am|pm) Utvid til å gjelde 24-timers tidsangivelse [01]?[0-9]|2[0-3]
Hvordan bruker vi dette ifb. php ereg( ”<expr>”, $streng [, grupper] ) eregi ( ”<expr>”, $streng [, grupper] ) ereg_replace( ”<expr>”, ”<inj>”, $streng ) eregi_replace( ”<expr>”, ”<inj>”, $streng ) split( ”<expr>”, $streng [, grense] ) spliti( ”<expr>”, $streng [, grense] )
Eksempel Gyldig e-post adresse? <?php $str = "ronnyma@math.uio.no"; if( ereg( "^[a-zA-Z0-9._%-]+@[a-zA-Z0-9.-]+\.[A-Z]{2,4}$", $str ) ) { //Valid } ?> ereg returnerer 0/1 på grunnlag av match eller ei
Et annet eksempel Erstatte ord i en tekst <?php $str = "Per han hadde en bondegård"; $str = ereg_replace( "Per", "Kari Bremnes", $str ); echo $str; ?> Kari Bremnes han hadde en bondegård Vi husker str_replace() fra forrige gang?
Enda et $str = "Jeg husker den gangen jeg red et esel som hesebleste i Estland"; $str = split( "e", $str ); foreach( $str as $value ) echo $value."<br>\n"; ?> 0 => J 1 => g husk 2 => r d 3 => n gang 4 => n j 5 => g r 6 => d 7 => t 8 => s 9 => l
Grupper i regex <?php $str = "Det er deilig å være Norsk i Danmark lige så"; eregi( "(lig).*(så)", $str, $regs ); foreach( $regs as $key => $value ) { echo $key." => ".$value."<br>\n"; } ?> 0 => lig å være Norsk i Danmark lige så 1 => lig 2 => så
Spørsmål? Have a nice day!