Reguláris kifejezések (RegEx)

A reguláris kifejezés (röviden: regex) egy mintaleíró karakterlánc, amelyet szövegkereséshez, -ellenőrzéshez és -manipulációhoz használunk. Segítségével könnyedén azonosíthatunk és kezelhetünk bonyolult szövegmintákat, például fájlneveket, időpontokat vagy kódrészleteket.

A legegyszerűbb példa a ^.*$ — ez minden szövegre egyezést ad. Ha nem szükséges bonyolult átnevezést vagy szűrést végezni, ez a minta tökéletes alapbeállítás.

Szintaxis

Speciális karakterek

Lookahead és Lookbehind

A néző (lookaround) kifejezések lehetővé teszik, hogy egy minta megelőző vagy követő feltételt vizsgáljunk anélkül, hogy az része lenne az egyezésnek.

Flag-ek (módosítók)

A regex viselkedése flag-ekkel módosítható (a legtöbb nyelvben azonos szintaxissal):

Például: /(?<id>\d+)/gi → kis/nagybetűtől függetlenül minden számot megtalál.

Csoportnevek és hivatkozások

A (?<name>…) konstrukció elnevezett csoportot hoz létre. Ez lehetővé teszi, hogy a feldolgozás során névvel hivatkozzunk az adott részre, ne csak sorszámmal.

Példa:

Minta:

^(?<time>\w{4})[-_](bkkinfo)[-_]*(?<date>.*)\.(?<ext>mp3|wav)$

Cél fájlnév: bkkinfo_${time}.${ext}

Eredmény: A 1020-bkkinfo.mp3 fájlból a rendszer bkkinfo_1020.mp3 nevet hoz létre.

Értelmezés:

  1. ^ - A fájlnév elejét jelöli. Biztosítja, hogy az illesztés a string legelején kezdődjön.
  2. (?<time>\w{4}) - Négy darab word karaktert vár (betű, szám vagy aláhúzás). Ezeket a karaktereket a time nevű csoportba menti. (A 1020-bkkinfo.mp3 esetén a time értéke 1020.)
  3. [-_] - Pontosan egy kötőjel (-) vagy aláhúzás (_). Ez választja el az időrészt a fix szövegtől.
  4. (bkkinfo) - Szó szerint a bkkinfo szöveget várja. Ez egy fix, kötelező azonosító a fájlnévben.
  5. [-_]* - Opcionálisan 0 vagy több kötőjel vagy aláhúzás. Tehát elfogadja, ha van, de ha nincs, azt is.
  6. (?<date>.*) - Bármilyen karakterláncot elfogad (akár üreset is). Az egészet a date nevű csoportba menti. Jellemzően dátum vagy egyéb kiegészítő információ. A példában 1020-bkkinfo.mp3 esetén ez üres, mert nincs köztes rész.
  7. \. - Egy literál pont. Elválasztja a fájlnevet a kiterjesztéstől. Escape szükséges, mert a pont regexben speciális karakter.
  8. (?<ext>mp3|wav) - A fájl kiterjesztése. Csak mp3 vagy wav lehet. Az értéket az ext nevű csoportba menti.
  9. $ - A fájlnév végét jelöli. Biztosítja, hogy a teljes string illeszkedjen, ne csak egy részlete.

Dinamikus minták

Előfordulhat, hogy a fájlnév-mintát nem statikusan (fix dátummal / órával), hanem dinamikusan szeretnénk megadni, például „mindig a mostani idő + 30 perc” alapján. Erre van lehetőség úgy, hogy a regex szövegébe PowerShell kifejezéseket ágyazunk be, amelyeket a rendszer a minta összeállításakor kiértékel, és a kiértékelt eredmény kerül bele a tényleges regexbe. Ezzel meg lehet oldani például, hogy minden órában az aktuális fájlokat beolvassuk és ugyanazon néven elmentsük. A $( … ) részek nem a regex részei, hanem PowerShell kifejezések.

 ^(?<date>$((Get-Date).AddMinutes(30).ToString('yyyyMMdd')))_HIREK-(?<hour>$((Get-Date).AddMinutes(30).ToString('HH')))30\.(?<ext>.+)$ 

Részletesen:

A leggyakrabban a Get-Date függvényt és annak valami módosítását használjuk, de minden szabvány PowerShell szintaxis működik. Az AddSeconds, AddMinutes, AddHours, AddDays függvények használata tipikus. Ha negatív értéket adunk meg, akkor értelemszerűen nem hozzáad, hanem kivon. Az előre gondolkodáshoz azonban pozitív értéket kell megadnunk.

Erre a legegyszerűbb példa egy óra eleji hírblokk, ami minden óra elején pár másodperccel az óraforduló után hangzik el. Ezt be szeretnénk tölteni már attól az időponttól, amikor már az előző biztosan lement. Példánkban nézzünk egy reggel nyolcas hírblokkot. 7:15-kor már biztosan lement az előző hírek, így igazából 7:15-től bármikor, ha elkészül a következő hírblokk, már beolvashatjuk. A rendszer egy olyan fájlnevet vár például, hogy 20251231_0800_HIREK.wav. Ebből a dátumot dinamikusan kell kezelnünk. A 20251231_08 karaktersort kell keresnünk, ez a Get-Date függvénnyel így néz ki:

(Get-Date).ToString('yyyyMMdd_HH')

Ha ezt lefuttatjuk, akkor 7:15-kor a kimenete az lesz, hogy 20251231_07, de nekünk már a nyolcasra végződő időpont kell, ezért hozzá kell adnunk 45 percet, így 7:15-kor már azt fogja mutatni, hogy 8 óra van, tehát a helyes kifejezés így fest:

(Get-Date).AddMinutes(45).ToString('yyyyMMdd_HH')

Gyakori minták

Mintákat legegyszerűbben a regex101 oldalon lehet létrehozni és tesztelni. A ChatGPT is pillanatok alatt generál regex mintát, ha megadjuk a kívánt logikát vagy fájlnévsémát. A powershell kifejezéseket egy egyszerű powershell ablakban idézőjelek között tudjuk tesztelni.