Grep parancs alapok

Grep
Grep

Erős a gyanúm, hogy mindenki hallott már a grep parancsról, de sokkal kevesebben használják ezt a kellemes és hatékony parancssori programot.

Bár ismeri mindenki, de egy kis bemutatás nem árt. A grep parancs jellemzően szöveges állományokban keres egy előre megadott mintát, szót, karakter sorozatot. Illetve azokat a fájlokat listázza ki melyekben az adott karaktersorozat megtalálható.

Az általános használata egyszerű, a belépő szintet mutatom csak be. Több paranccsal lehet kombinálni, ilyenek a find (komolyabban kereshetünk fájlok stb. közt) vagy hasznos lehet a pipe, azaz csővezetékkel való használata (|), de a már megismert xargs parancsot is használhatjuk.

Készíts be egypár szövegállományt egy külön könyvtárba, ezeken tudsz majd gyakorolni. Én alapból "nagyban" kezdtem, mert egy 9000 feletti alkönyvtárban lévő egy, vagy több sima szövegállományban és egy több ezres listában használtam... Az alkönyvtárakban elhelyezett szövegekben együttesen keresni, illetve hatalma szövegekben keresni - ezek adják a grep család erejét.

Szövegfájlokban keresni? Igen, ezek elég gyakoriak, de nem csak ilyen triviális területen lehet használni ezt a programot. Akár log fájlokban (ha azok szövegesek), akár pedig egyéb programok kimenetelében (pld. ls, cat, tree) kereshetünk. A forráskódokról, konfigurációs állományokról ne is beszéljünk, hiszen ezek kifejezetten olyanok, amikben keresgélni szoktak a felhasználók.

Akár egy szót, akár több szót, karakterláncot, akár pedig reguláris kifejezést (regexp) tudunk keresgélni.

Mikor nem jó a grep

A grep alapvetően sima szövegekben hatékony, így ha nem ilyen az állomány, akkor nem feltétlen lesz jó neked. A másik kizáró ok lehet, ha nem szeretnél terminálozni. Pár szövegállományban egyszerű szövegszerkesztővel is lehet keresni. Ha az kényelmesebb, akkor használd a grafikus megoldásokat.

A grep család

Igen, ha körbenézel az interneten, akkor láthatod, hogy többféle grep létezik: grep, egrep, fgrep, zgrep stb. Én most csak az alap grep parancsot vizsgálom, a többi vagy speciálisabb feladatokra alkalmas, vagy éppen többet tud, esetleg kényelmesebb.

A grep alap minden disztribúcióban, használd a telepítődet, ha nincs fenn.

Alap használata

A parancs a "Global Search and Print" rövidítése, amely magyarul "Globális Keresés és Nyomtatás" jelentésű. A grep parancs használata a következő:

grep [opcionális flagok] [keresendő szöveg] [fájl vagy könyvtár]

A man és a help nagyon sokféle megoldást felsorol, ami az első időben kissé ijesztő lehet, de semmi ok erre. Maximum féltucat olyan flag, kapcsoló van, amit érdemes ismerni az első időben. A többi, esetlegesen speciális megoldásokra akkor kell majd kitérni, ha erre igényed van.

grep "Zsuffa" minta1.txt

Zsuffa Tünde - A reménység oszlopa - Rádiószínház
Zsuffa Tünde - Király a Föld fölött - Rádiószínház
Zsuffa Tünde - Paprika rummal - egy kalandos élet - Rádiószínház

A megadott és idézőjelbe tett szöveget megkeresi a megadott fájlban. A fájl elérést elérési úttal is megadhatod, ha nem abban a könyvtárban vagy, amiben az állomány van. Teszteld le az előre bekészített állományokon.

Logikusan kikövetkeztethető, hogy mit jelent az alábbi keresési példák:

grep "Zsuffa" minta1.txt minta2.txt
grep "Zsuffa" *.txt

Logikus kérdés, ha kilistázza azokat a sorokat, amiket talál, akkor miképp tudjuk, hogy a sok állomány közül melyikben is vannak? Erre van a -H kapcsoló, ami beilleszti a találat elé a fájl nevét.

Pár hasznos grep flag

Az egyik leghasznosabb kapcsoló az -i, azaz kis és nagybetűk közt nem tesz különbséget.

grep -i "Zsuffa" minta1.txt

Itt jó a Zsuffa, de a ZSUFFA is, vagy bármilyen ki és nagybetűs írás. Hasznos, ha vélhetően a mondat elején is szerepel a keresett szó nagybetűs írásmóddal, és a mondatban kisbetűvel.

Hasznos, főleg nagyobb állományokban az -n kapcsoló. Ez kiírja a sor számát, ahol a keresett karakterlánc van.

grep -n "Zsuffa" minta1.txt

6683: Zsuffa Tünde - A reménység oszlopa - Rádiószínház
6684: Zsuffa Tünde - Király a Föld fölött - Rádiószínház
6685: Zsuffa Tünde - Paprika rummal - egy kalandos élet - Rádiószínház

A keresést segíti a sor száma.

Logikus feladat lehet a találatok átirányítsa szövegfájlba:

grep -i "Zsuffa" minta1.txt >> lista.txt

Megjegyzés: a kimenetek kinézete terminálonként eltérhet, ha szép színes a terminálod beállítása, sokkal attraktívabb, mint itt a beillesztett kimenet. Ha nem színes a kimenet, akkor a

grep --color -n "Zsuffa" minta1.txt

megoldás lehet. A leírások szerint ezt még fokozni is lehet, de én megelégszem az alap beállítással.

Megjegyzés: az idézőjelek elhagyhatóak, én megszokásból használom őket.

Hasznos kapcsoló a -w azaz csak azok a találatok jelenjenek meg, ahol teljes szó egyezés van.

grep -w "alma" minta1.txt

Itt az alma jó, de az almafa nem! Ha nincs a -w kapcsoló, akkor bármilyen alma karaktersor jó lesz találatnak, a birsalma és az almamag is.

Ha azokra a sorokra vagyunk kíváncsiak, amik NEM tartalmazzák a keresett karakterláncot, akkor a -v kapcsolót használjuk. Sokkal hasznosabb dolog lehet, ha nem csak a találati sort kapjuk meg, hanem az előtte és utána lévő megadott számút is. Így a szövegkörnyezetet is látni lehet.

-A, -B, -C - Mutasson megadott sort a találat felett, alatt vagy körül...

grep -A 3 -B 2 'error' logfile.txt

Ha az összes alkönyvtárban akarunk keresni a -R kapcsoló lesz a barátunk.

grep -R "Zsuffa" 

Ezzel kilistázzuk az összes olyan állományt, amiben a Zsuffa szó szerepel. Figyelem! Itt már nem a sorokat jeleníti meg, hanem a fájlok nevét, amiben az egyezés megtalálható.

Na, így nem kellene kezdeni, mert a grep nagy lelkesedésében minden állományban keresni fog, ami esetleg nem kívánatos. Nagyon kicsi az esélye (az adott példa feladatban, ahol a rádiós hanganyagaim közt keresek) egy mp3-asban ott lesz a Zsuffa karaktersorozat. Így korlátozni kell a fájltípusokat, amiben keressen.

Erre is van mód:

grep --include=\*.{txt,md} -Rnw '/könyvtár/útvonal/' "Zsuffa"

Azaz csak a txt és az md fájlokban keressen. itt példát látunk a teljes elérési útra, ha nem abban a könyvtárban vagyunk, ahol keresni akarunk.

Az ellenkezője, ha egy, vagy több kiterjesztést le akarunk tiltani, abban ne keressen.

grep --exclude=\*.{bak,tmp} -Rnw '/könyvtár/útvonal/' "Zsuffa"

Ha pedig alkönyvtárakkal dolgozunk, de többet ki akarunk zárni, akkor a

grep --exclude-dir={node_modules,.git,temp_*} -Rnw '/útvonal/könyvtár/' "Zsuffa"

Érdekes lehet a:

grep --include=\*.{txt,md} -Rnw '/könyvtár/útvonal/' -e "Zsuffa" -e "Tatár"

Itt már két karaktersort kezelünk, és az -e kapcsolót használjuk. A több karaktersort is keressen témát többféleképp is megadhatjuk, én (az átláthatóság miatt) így használom.

Ha problémás az elérési út, mert tele van space-vel, akkor azt mindenképp idézőjelbe kell tenni. Bár az space, üres hely nem tiltott a fájl, vagy könyvtárnevekben, azért érdemes kerülni őket! Ha már különleges karakterek, akkor egy érdekes dologra figyelni kell. A grep alapesetben kezeli a reg.experteket. Azaz nagyon jól tudunk összetettebb kereséseket is elvégezni, ha minimálisan ismerjük a szabványos kifejezéseket. De mi van, ha mi pont egy olyan szövegre, karaktersorra keresünk rá, ami amúgy ilyen különleges jelöléseket tartalmaz? Legyen a ^ példa. Ez a sor elején megfelelője a regexperteknél. Sokat használjuk, ha a sor elejére illeszkedést szeretnénk keresni.

grep -n "^minta" minta1.txt

alap esetben csak azokat listázza ki, ahol a minta a sor elején van, de nem azokat, amiknél a sor közepén. De én most a ^minta karaktersorozatra vagyok kíváncsi.

grep -n -E "\^minta" minta1.txt

megoldás jó lesz, mert egy -E kapcsolóval és egy un. menekülő karakterrel \ elmagyaráztuk, hogy most nem reg.exp funkcióval akarjuk használni a ^ karaktert, hanem pontosan a ^ karakterrel kezdődő és minta-val végződő sort keresem.

Ez egy-kettő ilyen jelnél még jó, de ha több van, akkor vagy az fgrep parancsot használjuk. Illetve ki tudjuk kapcsolni a reg.exp értelmezést az -F kapcsolóval.

Megjegyzés: a grep és a reg.expertek viszonya elég érdekes, mert többféle reg.expert jelölési típus van. Aki ilyent akar használni mélyebben, mint az alapok, annak érdemes utána olvasni.

Pár érdekesebb megoldás itt található.