Ugrás a fő tartalomra

Reguláris kifejezések alapok (Regexp)


A reguláris kifejezések, minta illesztéssel nagyon gyors keresés, szűrés megvalósítására szolgáló nyelvi elem a különböző programnyelvekben. Egy ütemben többciklusos végig kereséseket lehet kiváltani egy jól megfogalmazott mintával előálló találati listán.

mintaillesztés: ha ellenőrizni szeretnénk, hogy egy sztring (szöveg) megfelel-e bizonyos szabályoknak, vagy megtalálható(k)-e benne bizonyos szabályoknak eleget tévő rész sztringek. Mintha egy szűrőt/maszkot helyeznénk a szövegre és ezen ‘átfolyatva’ a szövegünket gyorsan ketté hasíthatjuk a megfelelők és nem megfelelők halmazára.
Ezen a találati listán művelet végzéssel sok adat tisztítási művelet megvalósítható.
Egyszerű minták
  • a normál karakterek saját magukra illeszkednek
  • a metakarakterek speciális jelentéssel bírnak, nem magukra illeszkednek
(pl: | ( ) [ ] { } ^ $ * + ? .)
Figyelem : ha előz meg egy metakaraktert, akkor az önmagát (a karaktert) jelenti
Metakarakterek és használatuk:
  •  .  illeszkedik minden karakterre, pl. /.ej/ illeszkedik a “fej”, “pej”, “tej” szavakhoz
  •  [abcdefg] illeszkedik a hét betű közül bármelyikre (egyre!)
  •  [a-g] megegyezik az előzővel: intervallum
  •  [^0-9] illeszkedik a számmal kezdődőkre
Kvantorok és használatuk: 
mindig a megelőző legkisebb részre vonatkozik
  •  {n} pontosan n-szeres ismétlés
  •  {m,n} legalább m-szeres, legfeljebb n-szeres ismétlés
  •  {m,} legalább m-szeres ismétlés
  •  {,n} legfeljebb n-szeres ismétlés
 vigyázat, a legelső illeszkedést keresi a program
  •  *  nulla vagy több előfordulás
  •  + egy vagy több előfordulás
  •  ? nulla vagy egy előfordulás
Horgonyok és használatuk:
  •  ^ sztring elejére illeszkedik, de csak ha a minta elején van
  •  $ sztring végére illeszkedik, de csak ha a minta végén van
 nem karakterekre, hanem pozíciókra illeszkednek
  •  b szóhatár, B nem szóhatár
Mintamódosítók és használatuk:
mintamódosítók a záró / után helyezhetők el
  •  i case-insensitivitást, az az kis-nagybetű érzéketlenséget idéz elő
  •  g globális keresést ill. helyettesítést idéz elő

Mintaillesztő metódusok és használatuk

JavaScript példa:

search metódus megadja azt a pozíciót, ahol a minta előfordul a sztringben, illetve -1-et, ha nem fordul elő benne: 
var str=”valamipengeinformatikus”;
var poz=str.search(/penge/); // poz=6
replace metódus egy adott mintát kicserél a második paraméterben adott sztringre
itt a $1,$2,. . .  használható a második paraméterben a reguláris kifejezés zárójelezett részkifejezésere való hivakozásként
például az első két szó felcserélése:
str.replace( /(bw+b)( *)(bw+b)/, “$3$2$1” ));
match metódus használatánál a visszatérési érték egy tömb:
– a g módosítót használva a tömbben szerepel minden illeszkedő részsztring
– a g módosító nélkül az első találatot követően a zárójelezett részsztrineg kerülnek a tömbbe


PHP példa:

$tiszta = preg_replace (“/[^a-zA-Z0-9 ]/”, “”, $koszos);
Figyelem betűköz van a 9 és ] között.

$tiszta = preg_replace (“/ +/”, ” “, $koszos); # több betőköz eggyel helyetesítés
$tiszta = preg_replace (“/^ /”, “”, $koszos); # sor elejéről a betőköz kivétele
$tiszta = preg_replace (“/ $/”, “”, $koszos); # sor végéről a betőköz kivétele


Oracle sql példa:

teleszemetelt szám kezdő/első számsor értékelése számként:
to_number(regexp_substr(piszkos_mezo,'[0-9]+’)) as tiszta_mezo
teleszemetelt szám kezdő/első számsor tizedets pont/vessző kezelés utáni értékelése számként:
to_number(regexp_substr(piszkos_mezo,'[[:digit:]]+[.,]*[[:digit:]]*’)) as tiszta_mezo
teleszemetelt határolókkal beírt számok össze keresése és egybe kiírása szöveges résszel kiegészítve:
replace(replace(regexp_replace(piszkos_mezo,'[‘ || chr(10)|| chr(13)|| chr(9)|| ‘”]+’,'[]’), ‘*’, ‘.’), ‘%’,’ százalék ‘) as tiszta_mezo
teleszemetelt határolókkal beírt számok össze keresése és kiírása:
regexp_replace(regexp_replace(regexp_replace(replace(to_char(nvl(piszkos_mezo,0)),’.’,’,’),’^(-)?,’,’10,’),’,(.)$’,’,10′),’^(-)?([[:digit:]]+)$’,’12,00′) as tiszta_mezo
regexp_replace(replace(to_char(piszkos_mezo),’.’,’,’),’^([-]*),’,’10,’) as tiszta_mezo
nvl(substr(regexp_replace(trim(piszkos_mezo),'[^[:digit:]]’),1,6),’190101′) as tiszta_mezo


Összegoglalás POSIX minták és jelentésük:

Egys. minta        Megfelel    Jelentése
[:upper:]              [A-Z]          Nagybetűk
[:lower:]               [a-z]           Kisbetűk
[:alpha:]               [A-Za-z]   Nagy- és kisbetűk
[:alnum:]       [A-Za-z0-9]  Számjegyek, nagy- és kisbetűk
[:digit:]                [0-9]            számjegyek
[:xdigit:]        [0-9A-Fa-f]    hexadeciális számjegyek
[:punct:]             [.,!?:…]        elválasztó karakterek
[:blank:]               [ t]            szóköz és TAB
[:space:]        [ tnrfv] üres karakterek
[:cntrl:]                                     vezérlő karakterek
[:graph:]     [^ tnrfv] nyomtatásvezérlő karakterek
[:print:]       [^tnrfv] nyomtatásvezérlő karakterek és szóköz

vb tisztítási minta (nem regexp):

‘———————————————————————-
‘   1. példa
Sub a_tiszt()
‘ Törli:
‘ minden bekezdés elejéről és végéről a szöközöket, tabulátorokat,
‘ az üres sorokat.
‘ Minden szóközsorozatot egy szóközre cserél.
Dim Válasz As Integer
Válasz = MsgBox(“Ez a makró a dokumentum tisztítását végzi, azaz:” & vbNewLine & _
“- minden bekezdés elejéről és végéről törli a szöközöket, tabulátorokat;” & vbNewLine & _
“- törli az üres sorokat;” & vbNewLine & _
“- az egymást közvetlenül követő szóközöket egy szóközre cseréli.” & vbNewLine & vbNewLine & _
“Indulhat a makró?”, vbYesNo Or vbQuestion, “Alapvető tisztítás”)
If Válasz = vbYes Then
With ActiveDocument.Content.Find
.ClearFormatting: .Replacement.ClearFormatting: .Format = False
.Forward = True: .Wrap = wdFindContinue
.Text = ” ^p”: .Replacement.Text = “^p”
‘ ciklus
While .Execute(Replace:=wdReplaceAll): Wend
.Text = “^p “: .Replacement.Text = “^p”: While .Execute(Replace:=wdReplaceAll): Wend
.Text = “^p^t”: .Replacement.Text = “^p”: While .Execute(Replace:=wdReplaceAll): Wend
.Text = “^t^p”: .Replacement.Text = “^p”: While .Execute(Replace:=wdReplaceAll): Wend
.Text = “^p^p”: .Replacement.Text = “^p”: While .Execute(Replace:=wdReplaceAll): Wend
.Text = ” “: .Replacement.Text = ” “: While .Execute(Replace:=wdReplaceAll): Wend
End With ‘ ActiveDocument.Content.Find
End If ‘ Válasz = vbYes
End Sub ‘ a_tiszt
‘———————————————————————-
 ‘————————————————————
‘ 2. példa 
Option Explicit
‘ Html fájlok szögegfájlokká alakítása.(regexp)
‘ objektumok
Dim Hej, RegKif, FajlRendszer, Mappa, Fajl, SzovegFajl
‘Dim Héj, RegKif, FájlRendszer, Mappa, Fájl, SzövegFájl
Dim Szoveg, X
Function HTMLbolSzoveg(S)
‘ először törlünk mindent a <body> tag előtt és a </body> tag után
X = InStr(1, S, “<body”, vbTextCompare)
S = Trim(Right(S, Len(S) – X + 1))
X = InStr(1, S, “</body”, vbTextCompare)
S = Trim(Left(S, X – 1))
With RegKif
.IgnoreCase = True: .Global = True
‘ a <td> tagokat tabulátorra cseréljük  Igaz, hogy így az első td helyetti tab fölösleges, de  a </td> elhagyható, ezért kell a <td>.
.Pattern = “<td(.)?>”
S = .Replace(S, vbTab)
‘ a <tr> tagokat újsorra cseréljük
.Pattern = “<tr(.)?>”
S = .Replace(S, vbNewLine)
‘ a <br> tagokat újsorra cseréljük
.Pattern = “<br(.)?>”
S = .Replace(S, vbNewLine)
‘ törlünk minden <> pár közötti szöveget
.Pattern = “<(.|n)+?>”
S = .Replace(S, “”)
End With ‘ RegKif
‘ végül javítjuk a maradékot
S = Replace(S, “<“, “&lt;”) ‘ a pár nélküli csúcsos zárójelek
S = Replace(S, “>”, “&gt;”)
S = Replace(S,”&nbsp;”,” “)
‘ kész
HTMLbolSzoveg = Trim(S)
End Function ‘ HTMLbolSzoveg
‘ itt kezdődik a főprogram
Set Hej = WScript.CreateObject(“WScript.Shell”)
Set FajlRendszer = CreateObject(“Scripting.FileSystemObject”)
Set Mappa = FajlRendszer.GetFolder(Hej.CurrentDirectory)
Set RegKif = New Regexp
For Each Fajl In Mappa.Files
‘ csak a htm-mel kezdődő kiterjesztésű fájlokkal foglalkozunk
If Left(FajlRendszer.GetExtensionName(Fajl),3) = “htm” Then
Set SzovegFajl = FajlRendszer.OpenTextFile(Fajl.Path)
Szoveg = SzovegFajl.ReadAll: SzovegFajl.Close
Set SzovegFajl = FajlRendszer.CreateTextFile(Fajl.Path & “.txt”, True)
SzovegFajl.Write HTMLbolSzoveg(Szoveg): SzovegFajl.Close
End If ‘ Left(FajlRendszer.GetExtensionName(Fajl),3) = “htm” Then
Next ‘ Each Fajl In Mappa.Files
‘ vége, kitakarítunk
Set RegKif = Nothing
Set Mappa = Nothing: Set Fajl = Nothing
Set FajlRendszer = Nothing: Set SzovegFajl = Nothing
 ‘————————————————————
‘————————————————————–
‘ 3.minta
‘ A kötőjelet tartalmazó szavakat úgy olvas be, hogy ha már benne van elválasztva, akkor törli belőle a kötőjeleket
Option Explicit
‘ HTML fájlokból gyűjti ki a HTML tagokon kívüli szavakat a szólista.txt nevű szövegfájlba.
Const vbForReading = 1, vbForWriting = 2, vbForAppending = 8
Dim Hej, RegKif, FajlRendszer
Dim NaploFajl, Mappa, Almappa, Fajl, SzovegFajl, SzoListaFajlNeve
Dim Kiterjesztes, Szavak, Szotar, SzoTomb, Szo, SzoElvalasztva, Talalatok, Talalat
Dim KezdesiIdo, TeljesIdo
Set Hej = CreateObject(“WScript.Shell”)
Set RegKif = New RegExp
Set Szotar = CreateObject(“Scripting.Dictionary”)
Set FajlRendszer = CreateObject(“Scripting.FileSystemObject”)
KezdesiIdo = Now
With RegKif
.IgnoreCase = True: .Global = True: .MultiLine = True
End With ‘ RegKif
Szotar.CompareMode = vbTextCompare
Set Mappa = FajlRendszer.GetFolder(Hej.CurrentDirectory)
With FajlRendszer
Set NaploFajl = .CreateTextFile(.BuildPath(Mappa, .GetBaseName(WScript.ScriptName) & “.log”))
End With ‘ FajlRendszer
NaploFajl.WriteLine Now & “: Kezdés.”
SzoListaFajlNeve = FajlRendszer.BuildPath(Mappa, “szólista.txt”)
If FajlRendszer.FileExists(SzoListaFajlNeve) Then
Set SzovegFajl = FajlRendszer.OpenTextFile(SzoListaFajlNeve)
SzoTomb = Split(SzovegFajl.ReadAll, vbNewLine): SzovegFajl.Close
For Each SzoElvalasztva In SzoTomb
‘ A szóeleji csillagokat töröljük
SzoElvalasztva = Replace(SzoElvalasztva, “*”, “”)
‘ A szótárbeli kulcsszó a kötőjel nélküli szó lesz.
Szo = Replace(SzoElvalasztva, “-“, “”)
If Szo <> “” Then Szotar.Add Szo, SzoElvalasztva
Next ‘ Each SzoElvalasztva In SzoTomb
‘ A SzóTömb már nem kell, felszabadítjuk a memóriát.
ReDim SzoTomb(0)
End If ‘ FajlRendszer.FileExists (SzoListaFajlNeve)
NaploFajl.WriteLine Now & “: Korábbi szólista beolvasás kész.”
Szavak = “”
‘ Beolvassuk az összes HTML fájlt.
Bejaras Mappa
NaploFajl.WriteLine Now & “: Mappabejárás kész.”
Szavak = LCase(Szavak)
‘ Eltávolítjuk a HTML tagokat.
RegKif.Pattern = “<(.|n)+?>”: Szavak = RegKif.Replace(Szavak, ” “)
Szavak = Replace(Szavak, “<“, “&lt;”): Szavak = Replace(Szavak, “>”, “&gt;”)
‘ A már meglévő elválasztásokat megtartjuk.
RegKif.Pattern = “&shy;|&ndash;|&mdash;”: Szavak = RegKif.Replace(Szavak, “-“)
‘ A többi HTML karaktert szóközökre cseréljük.
RegKif.Pattern = “&w+;”: Szavak = RegKif.Replace(Szavak, ” “)
‘ A szóhatárt jelentő karakterek cseréje szóközre.
RegKif.Pattern = “[‘;,:/@!””*$?.[]()]”: Szavak = RegKif.Replace(Szavak, ” “)
‘ Minden szó külön sorban legyen.
RegKif.Pattern = “s+”: Szavak = RegKif.Replace(Szavak, vbNewLine)
‘ Nem kellenek a számok sem (a csak számjegyet tartalmazó sorok).
RegKif.Pattern = “^d+$”: Szavak = RegKif.Replace(Szavak, “”)
‘ Az új szavakat hozzáadjuk a szótárhoz.
SzoTomb = Split(Szavak, vbNewLine)
For Each SzoElvalasztva In SzoTomb
Szo = Replace(SzoElvalasztva, “-“, “”)
‘ A háromnál kevesebb betűs szavakat kihagyjuk, úgyse kell elválasztani őket.
If Len(Szo) > 3 Then
‘ A már bent lévő szavakat is kihagyjuk.
If Not Szotar.Exists(Szo) Then
Szotar.Add Szo, SzoElvalasztva
End If ‘ Not Szotar.Exists(Replace(Szo,”-“, “”))
End If ‘ Len(Szo) > 3
Next ‘ Each SzoElvalasztva In SzoTomb
ReDim SzoTomb(0)
‘ Az el nem választandó szavakat töröljük, az elválasztandókat pedig  ha még nincsenek elválasztva, megjelöljük.
For Each Szo In Szotar
‘ Elágazás a szóban lévő magánhangzók száma alapján.
RegKif.Pattern = “[aáeéiíoóöőuúüű]”: Set Talalatok = RegKif.Execute(Szo)
Select Case Talalatok.Count
Case 0, 1
‘ A kettőnél kevesebb magánhangzót tartalmazó szavakat nem kell elválasztani.
Szotar.Remove Szo
Case 2
‘ Ha pontosan két magánhangzó van a szóban és legalább egyik a szó  szélén (elején vagy végén) van, akkor nem kell elválasztani.
RegKif.Pattern = “^[aáeéiíoóöőuúüű]|[aáeéiíoóöőuúüű]$”
If RegKif.Test(Szo) Then
Szotar.Remove Szo
Else ‘RegKif.Test(Szo)
If InStr(Szotar.Item(Szo), “-“) = 0 Then Szotar.Item(Szo) = “*” & Szo
End If ‘ RegKif.Test(Szo)
Case Else ‘ Talalatok.Count
‘ Ha kettőnél több magánhangzó van egy szóban, és még nincs elválasztva,  akkor megjelöljük egy csillaggal.
If InStr(Szotar.Item(Szo), “-“) = 0 Then Szotar.Item(Szo) = “*” & Szo
End Select ‘ Talalatok.Count
Next ‘ Each Szo In Szotar
‘ Végül kiírjuk a kész szövegfájlt.
Set SzovegFajl = FajlRendszer.CreateTextFile(SzoListaFajlNeve, True)
SzovegFajl.Write Join(Szotar.Items, vbNewLine): SzovegFajl.Close
NaploFajl.WriteLine Now & “: Kész. Teljes idő: ” & TimeSerial(0, 0, DateDiff(“s”, KezdesiIdo, Now)): NaploFajl.Close
‘ Kitakarítunk.
Set Mappa = Nothing: Set Almappa = Nothing
Set Fajl = Nothing: Set SzovegFajl = Nothing: Set NaploFajl = Nothing
Set FajlRendszer = Nothing: Set Szotar = Nothing
Set Talalatok = Nothing: Set Talalat = Nothing
Set RegKif = Nothing: Set Hej = Nothing
Private Sub Bejaras(Mappa)
‘ Rekurzív eljárás.
For Each Fajl In Mappa.Files
Kiterjesztes = FajlRendszer.GetExtensionName(Fajl)
If LCase(Left(Kiterjesztes, 3)) = “htm” Then
Set SzovegFajl = FajlRendszer.OpenTextFile(Fajl.Path)
Szavak = Szavak & SzovegFajl.ReadAll: SzovegFajl.Close
End If ‘ LCase(Left(Kiterjesztes, 3)) = “htm”
Next ‘ Each Fajl In Mappa.Files
NaploFajl.WriteLine Now & “: ” & Mappa.Path
For Each Almappa In Mappa.SubFolders
Bejaras Almappa
Next ‘ Each Almappa In Mappa.SubFolders
End Sub ‘ Bejaras

Megjegyzések