Grep és a regex-ek, alapfokon

Linux kezdő
Linux kezdő

A regex-eket nem nagyon szeretik az emberek, bár elég jól használhatóak. Erről már volt szó, jellemzően az átnevezéssekkel kapcsolatban hoztam példát. Ez az egyik olyan terület, aminél egy átlagfelhasználó ezeket használni szokta. A másik a grep, sed stb. programok halmaza, ahol valami szövegben keresünk, vagy cserélünk egy-egy karaktersort. Ez alapesetben egy nagyon kis réteget érint, hiszen ezeknél sima szövegfájlokkal dolgoznak, és pontosan ezeket a funkciókat jellemzően megtaláljuk a grafikus szövegszerkesztőben is. Ha csak sima szövegfájlokban használjuk, és amúgy is egy kényelmes, grafikus (pld. geany) szövegszerkesztővel is megoldhatjuk ezt… akkor mi a fenéért használnám? A kérdés jogos! A legtöbb esetben nem is kell ezeket a fura parancssoros megoldásokat használni, de ismerni kell(ene).

Miért használjunk regex-eket és sed, grep és egyéb programot?

Parancssorból elérhető, gyors megoldás, ha kezelni tudod őket. Ha csak grafikus felületen dolgozol, akkor nem feltétlen lesz erre szükséged.

Tömegmunkára alkalmas ez a megoldás. Ha egy műveletet (pld. csere, keresés) szeretnél megtenni nagyon sok fájlon, akkor ezzel simán megteheted. Ez sem egy mindennapi feladat, de pár alkalommal jól jöhet.

Scriptben, vagy csővezetékben (egymásután összekapcsolt parancsok, ahol az egyik kimenetét dolgozza fel a következő automatikusan) igencsak jól használható. Ez a fő terület, amiért érdemes átgondolni az alapok elsajátítását. “Röptében” dolgozod fel az adatokat, és csak az eredményt kapod meg.

Grep, a legismertebb szövegben kereső eszközünk

Ez egy nagyon összetett program, de itt csak pár hasznosnak vélt alapot nézünk meg. Használhatsz bármiféle sima szövegfájl, ami tetszik, vagy konfigurációs fájlt is, hiszen azok is általában szövegek. Értelemszerűen másolaton dolgozunk!

Meg szeretnéd tudni, hogy miért nem jelenik meg egy oldal a böngésződben. Az merül fel, hogy a hosts fájlban blokkolt, a már ismertetett kis programmal.

grep 'vernyomasgondok.hu' /etc/hosts

Ahogy látni nem egy nagy dolog, a grep, amit keresünk, majd a miben keressen a felépítés. Próbáld ki bármely txt fájlban, egy adott szóra keresve. Ne csak olvass, gyakorolj is.

Joggal mondhatjuk: bizony ezt a geany, vagy más egyéb, egyszerű, és grafikus szövegszerkesztőben is megtehetjük. Ez igaz is, de mi van ha több fájlon kell keresni, esetleg alkönyvtárakban is? Én nagyon sok txt fájlt használok, mert egyszerű, ha nincs szükség különösebb formázásra, akkor nagyon kellemes megoldás, mert mindenhol egyformán jól olvasható. Illetve sok html-ben mentett is van, ami szintén sima szöveg. De egy általánosabb téma, ha sok konfigurációs fájlban akarsz keresni, akkor ezzel hatékonyan megteheted. Ilyen problémám  volt egy telepítés után, amikor az openbox nem pont azt tette, amit én elgondoltam, így meg kellett keresni, melyik program configjai hivatkoznak arra a beállításra. Most az egyszerűség kedvéért keressük meg a home/.config könyvtáradban az összes olyan fájlt, amiben szó van az openbox-ról, azaz explicit leírták bennük ezt a szót: openbox.

grep -r 'openbox' /home/laci/.config

Ki is listázza, amit kell. Hm… bár lehet visszafele görgetni a legtöbb terminálban, de azért ez nem túl kényelmes. Jó lenne ezt egy szövegfájlba belerakni, a későbbi tanulmányozás és a kényelem miatt. Ezt egy átirányítással tudjuk megtenni:

grep -r 'openbox' /home/laci/.config > eredmeny.txt

Ezután már a megadott fájlba írja be a kimenetet, azaz azt a listát, amit előbb a terminálban láttunk. Próbáld ki! Majd nyisd meg a fájlt egy szövegszerkesztővel.

Kacsacsőr, és két kacsacsőr – átirányítás fájlba

A fenti példa nagyon jól mutatja, hogy egy parancs kimenetét át tudjuk irányítani fájlba is, hogy azzal később valamit tegyünk. Erre a > jel szolgál. A kapott kimenettel felülírja a fájl tartalmát, ha van ilyen fájl. Ha nincs, akkor létrehozza és abba ír. Ebből két következtetést tudsz levonni: ha létezik a fájl, akkor annak az előző tartalma el fog tűnni. Örökre. Ami kellemetlen, ha az egy fontos fájl. Kellemes, mert így „felülírod” a tartalmát visszaállíthatatlanul – abban majdnem biztosan nem kutakodik eredménnyel senki a régi tartalom megszerzéséért. A másik fontos, de ebből következő, hogy ha több parancs kimenetét is meg akarod tartani (pld. több lehetséges könyvtárban is keressen openbox bejegyzést a fájlokban) egy fájlban, ez így nem lesz jó. Az utolsónak megadott parancs kimenete lesz csak benne. Ez nagyon jegyezd meg, mert scriptek építésénél sokszor érdemes egy-egy részlet kimenetét fájlba menteni, hogy ellenőrizni tudd az adott lépést, vagy egy-egy kimeneti fájlt tovább feldolgozni is lehet. Ha nem figyelsz a jó névválasztásra, akkor abból gubanc lesz!
Másnak is jó lett volna a több parancs kimenete legyen egy fájlban, így megoldották, hogy ne felülírja, hanem hozzáfűzze a tartalomhoz a kimenetet:

grep -r 'openbox' /home/laci/.config > eredmeny.txt
grep -r 'openbox' /home/laci/.bin >> eredmeny.txt

Így a két könyvtárban talált openbox karaktersort tartalmazó sorok egy fájlba kerülnek, és meg tudom nézni őket.

Horgonyok, és egyéb regex-ek a grep-nél

A grep teljes mértékben kezeli a regex-eket, így nem csak egy szó tudsz megadni, hanem bármiféle összeállítást, amire képes a regex igencsak nagy repertoárja. Ilyen lehet pld. az email cím, telefonszámok, fájl nevek, letöltési linkek, egyebek kinyerése bármennyi szövegfájlból, honlap forráskódból. A honlap forráskódjában való turkálásra tervezek egy scriptet írni, majd azt bemutatni…

Pár egyszerű megoldás, valóban csak azért, hogy lásd az egyszerűségét. Újra a hosts fájlunkat nézetjük.

Mennyi felsorolt cím van?

grep -c '.' /etc/hosts

Keress bármilyen sort, amiben legalább egy karakter van. Első körben ez 270677-et ad, ami szép szám, de nem igaz, mert vannak olyan sorok is, ami bizony kommentek, vagy az eredeti hosts fájl része. Mivel ismerjük a felépítést:

#
0.0.0.0 0–e.info
0.0.0.0 0-hjsochvj-ios-1-2-3.mobile-sdk-api.intercom.io

Láthatjuk, hogy a 0.0.0.0 a sor kezdete, így keressünk rá az sor elején lévő ilyen karaktersorra:

grep -c '^0.0.0.0' /etc/hosts

Szuper! A ^ jelet ismerjük, volt róla szó…

Mennyi a hu domén, amit blokkolunk?

Első gondolata, hogy simán keressünk a hu karaktersorra és az jó lesz, de nem! Egy weboldal címében is lehet hu, és még olyan is, hogy .hu! Ha nem tudod 100% biztonsággal kizárni, hogy egyik sem fordul elő, akkor ennél árnyaltabb megoldást kell keresni. A .hu csak a sor végén lehet, hiszen a szabványos doménnév az már csak ilyen.

grep -c '.hu$' /etc/hosts

173 nálam, és nézzük is meg ezeket, azaz küldjük ki egy fájlba az eredményt:

grep '.hu$' /etc/hosts > blokkolt.hu

Egy kellemes megoldás a kommentek kiszedése egy config-ból

Sok beállító fájlban, scriptben rengeteg # sor van, ami a kikommentelt, magyarázó részt mutatja. Ha kapok egy beállításról leírást, akkor sok esetben alig lehet megtalálni a tényleges beállítási sorokat a rengeteg komment közt.

Itt csak a mintára NEM illeszkedő sorokat akarom látni, ami NEM # jellel kezdődik.

-v, –invert-match a nem illeszkedő sorok kiválogatása

Ezt mondja az help. Nem árt átnézni minden program help-jét, mert sok jó ötletet adnak, és meg is kell(ene) ismerni a lehetőségeket!

Akkor próbáljuk is meg:

grep -v '^#' /etc/fstab

Bár ebben kevés a komment, de mindenkinél van ilyen fájl, és így láthatja az eredményt. Ezt is át lehet irányítani egy fájlba, ha nem elég a terminálba kiírt szöveg.
Ez bár a legtöbb esetben jól működik, de van, amikor nem: ha a kommentet nem külön sorba írja a programozó, hanem valahol a sor közepén, a lényeges rész után kezdi egy # jellel. Ez is szabályos, de nem túl elegáns megoldás.

Üres sorok, és a megjegyzések törlése

grep -v '^#' /etc/sudoers

majd a

grep -v '^$'

^$ jel az eleje és a vége egybeesik, a kettő közt nincs semmi, így lehet lefordítani. Érdemes megjegyezni.

Ok ez nem fog menni, mert az első a kommentek nélküli kimenetet adja, a második meg az üres sorok nélkülit.

Ilyenkor használhatjuk a csővezetéket, egybe kapcsoljuk a parancsokat. Első kimenete lesz röptében, kiíratás nélkül a második bemenete. Pont mint a csövekben (pipe): az elején bemegy valami, a végén kijön a kész termék. Igencsak hasznos megoldás, sokat használhatjuk scripteknél.

grep -v '^#' /etc/sudoers | grep -v '^$' > a_lényeg.txt

A sudo előtte ajánlott! A | pedig az AltGr +w együttes lenyomásával kapható meg.

A művelet annyi, hogy az első részben kiszedte a nem kommentelt sorokat, ami lehet üres sor is. Majd ezt az eredményt átadta a következő résznek, ami pedig kiszedte a nem üres sorokat és az eredmény így került ki a csővezetékből a szövegfájlba. Igen, ez olyan mint amikor a manufaktúrákat leváltotta az ipari forradalom a szalagmunkával. Lényegesen gyorsabban készültek el a T-modellek, és olcsóbbak is lettek.

Fontos! Az eredeti fájlhoz nem nyúltunk, nem írtunk bele. Beolvasta a grep (jegyezd meg: képes fájlt beolvasni, nem kell más programmal beolvastatni!), majd dolgozott a beolvasott adatsorral, egy belső tárolójában, és a végén vagy kiírta a terminálra, vagy a megadott fájlra. Bár megoldható, hogy az eredeti fájlba írassuk ki a kimenetet, a végeredményt, de az első időben ezt hanyagoljuk! Ha valami nem úgy sül el, ahogy akarod, akkor – és erről már volt szó – az eredeti tartalom felülírásra kerül.
Haladó grep szakik nyilván ovisnak tartják ezt a megoldást, mert elegánsabb a

grep -Ev '^#|^$' /etc/sudoers

de az én megoldásomnak van egy előnye: a kezdő előbb az első tagot kiíratja egy fájlba, megnézi. Majd ha jó, akkor hozzáteszi a második tagot és azt is kiíratja. Így lépésenként kontrollálhatja a részfeladat eredményét.

Nem csak kér grep-et köthetsz össze, hanem eltérő programot is. A futó processeket kilistázhatod a
ps aux-al, ami elég nagy adathalmaz. Jó lenne, ha egy adott programra kereshetnénk:

ps aux | grep 'strawberry'

Azaz a zenelejátszómról szeretnék csak infót kapni. Bármely adatfolyamban kereshetsz így.

Ma megtanultunk, hogy van grep kereső, szövegkereső program, ami nagyon sokat tud, így érdemes rákeresni az interneten pár példára, illetve a leírásokat, helpet, man-t átfutni. Messze többet tud, mint amiről itt szó volt!
Megtanultuk a program kimenetét fájlba kiíratni, ami egy hasznos dolog, de veszélyes is: soha ne írasd saját magára ki a fájlt!
Megtanultunk egymásután fűzni programot csővezetékkel. Ezt érdemes scritpben, alias-ban használni, nem pedig begépelni, ha hosszabb és többször kell.

Itt jegyzem meg, hogy ha bármelyik cikkemmel, videómmal kapcsolatban építő jellegű gondolatod van, azt oszd meg velem. Vagy a linuxvideok/ide tudod mi jön/protonmail/ide is/com címre, vagy a https://discord.gg/7DdbM9g discord csatornán elérsz.

A programot 2020. márciusában próbáltam ki.

Related Posts