Przeszukiwanie plików
Program grep przeszukuje plik i wyświetla linie pasujące do wzorca (czyli linie które zawierają szukane słowo).
składnia:
grep szukane_slowo plik
# wiersze zawierające słowo "Linux" w pliku "konfiguracja":
grep Linux konfiguracja
# wiersze ze słowem mariusz w pliku /etc/passwd
grep mariusz /etc/passwd
# wiersze ze słowem Linux we wszystkich plikach *.txt, *.htm i *.html
grep Linux *.{txt,htm?}
Krótki skrypt proszący o nazwę szukanego słowa oraz pliku tekstowego do przeszukania:
#!/bin/bash
echo -n "Szukane slowo: "
read slowo
echo -n "Plik: "
read plik
grep "$slowo" "$plik"
Polecenie
ls | grep ja
wyświetli wszystkie pliki których nazwa zawiera łańcuch ja np. ja, janek, aleja itp.
Gdy chcemy wyświetlić liki do któryh wszyscy mają dowolny dostęp:
ls -l | grep rwxrwxrwx
Wyrażenie:
grep Anna *
Będzie szukać wyrazu Anna we wszystkich plikach bieżącego katalogu
Uzyteczne opcje:
-i - nie zwraca uwagi na wielkość liter
-l - wypisuje tylko nazwy plików
-c - wyświetla tylko numery linii
-w - wyszukuje konkretne słowo tzn. jeśli zażyczymy sobie ciąg 'ma' to zwróci tylko te wiersze w których wystąpił dwuliterowy wyraz 'ma' a nie np. 'mama'
-r - przeszukuje katalog rekursywnie tzn. zagłębia się w strukturę katalogów szukając wyrażenia również w podkatalogach
-C , -C 1, lub -1 - wypisuje określoną ilość linii (domyślnie 2) kontekstu na wyjściu
-E -interpretuje wzorzec jako rozszerzone wyrażenie regularne
-e-używa wzoraca jako wzorac (użyteczne dla ochronienia wzorów zaczynających się od -)
-v -wybiera linie nie pasujące
-x -wybiera tylko te dopasowania które pasują do całej linii
Grep a cytowanie
grep "$HOME" *
podstawia za wyrażenie wartość zmiennej oznaczającej katalog domowy a więc działa tak samo jakbyśmy napisali:
grep "/home/mariusz" *
Gdyby chodziło nam o napis $HOME należy zastosować pojedyńcze cudzysłowy:
grep '$HOME' *
Wyrażenia regularne a grep
Wyrażenia regularne ulatwiaja nam szukanie łańcuchów (wyrazów) w plikach lub w wynikach poleceń wyrzucanych przez konsolę.
Kropka . dopasowuje dowolny pojedynczy znak czyli chcemy wypisac:
- wyrazy trzyliterowe w pliku:
grep ... plik.txt
- trzyliterowe wyrazy które koncza sie końcówką la
grep .la plik.txt
- pięcioliterowe wyrazy mające na trzecim miejscu m a na pozostalych miejscach dowolne znaki
grep ..m.. plik.txt
Jeśli naprawdę chodziłoby nam o wyszukanie kropki np wiersza zawierającego nazwę obraz.gif to znak kropki trzeba "zamaskować" czyli postawić przed nim znak prawego ukośnika:
grep 'obraz\.gif' plik
Znak ^ dopasowuje występujące przed nim wyrażenie do początku wiersza.
- wyrazy rozpoczynajace sie na literę M
grep ^M plik
- wyrazy rozpoczynające się na Mar
grep ^Mar plik
wypisze: Marta Mariusz Marian martenowski
Znak $ działa dokładnie odwrotnie czyli dopasowuje wyrażenie do końca wiersza (piszemy go za wyrażeniem):
- wyrazy kończące się na -la
grep la$ plik
wypisze: ala ela ola krasnala itp.
Wyrażenie w nawiasach kwadratowych [] dopasowuje jeden dowolny znak znajdujący się między nawiasami np.:
- dopasowanie wyrazow ala ola ela
grep [alo]la plik
- dopasowanie wyrazow kot, kat
k[oa]t
Dzieki nawiasom możemy dopasowywać całe zakresy znaków. Przypuśćmy że chcielibyśmy wyświetlić wyrazy zawierające na drugim miejscu dowolną literę:
Zgodnie z tym co poznaliśmy do tej pory napisalibyśmy
a[abcdefghijklmnoprstuwxyz]la
Okazuje się że można zrobić to o wiele prościej - ciąg zawierający wszystkie wyrazy zastąpić takim: [a-z]
a[a-z]la
Oczywiście nie musimy wyszukiwać całego przedziału: można napisać po prostu [a-d]
Tutaj nadmienie jeszcze że aby wypisać również znaki zawierające wielkie litery należy napisać:
[A-Za_z]
W taki sam prosty sposób możemy postąpić z liczbami:
zamiast pisać [0123456789] wystarczy:
[0-9]
Ważna ciekawostka:
Operator [^ ] dopasowuje dowolny znak który nie znajduje się w nawiasach.
Jeżeli chcemy wypisać wszystkie znaki NIE zawierające znaku z tego przedziału dodajemy W NAWIASIE znak ^.
auto_[^4-6]
wyszuka:
auto_1 auto_2 auto_3
ale auto_4 czy auto_5 juz nie.
Wszystkie znaki które nie są cyframi:
[^0-9]
Pamiętajmy że znak ^ służy też do wyszukania wyrażeń znajdujących się na początku łańcucha znaków, jednak wtedy nie znajduje się w nawiasach.
Gwiazdka * oznacza że poprzedzający element będzie dopasowany 0 lub dowolną ilość razy:
An*a
dopasuje wyrazy Ana Anna lub Annnnnna
Jak widać gwiadka ma w wyrażeniach regularnych inne znaczenie niż przy generowaniu nazw plików.
Wyrażenie kropka gwiadka oznacza dowolny ciąg znaków:
.*
dopasuje dowolną ilość znaków obojętnie jakich np wyrażenie:
.*r
dopasuje zarówno wyraz monitor jak i komputer
Nawiasy zwykłe określają zgrupowany ciąg znaków który staje się wyrażeniem regularnym. Chodzi o to że gdy napiszemy wyrażenie:
auta*
to może ono oznaczać auta autaaa itp. a gdy dodamy nawiasy:
(aut)*
to teraz zamiasy gwiazdki pojawi się już nie jedna litera tylko całe wyrażenie z nawiasu np.:
autaut autautaut itp.
Plus (+) znacza że poprzedzający element będzie dopasowany jeden lub więcej razy.
{n} Poprzedzający element pasuje dokładnie n razy.
{n,} Poprzedzający element pasuje n lub więcej razy.
{,m} Poprzedzający element jest opcjonalny i pasuje co najwyżej m
razy.
{n,m} Poprzedzający element pasuje co najmniej n razy, ale nie więcej
niż m razy.
Znak zapytania (?) oznacza że poprzedzający element jest opcjonalny i występuje najwyżej raz.
grep 'stacja/?' plik
dopasuje wyrazy stacj stacja ale juz np. stacjaa nie da rady.
grep 'Jan/(ek/)/?' plik
dopasuje Jan lub Janek.
Przy wybieraniu wierszy można używać kilku wyrażeń z których musi być spełnione chociaż jedno żeby zwróciło wyniki. Używamy do tego operatora OR (LUB)
grep -E "^c|^d" /etc/termcap
Wybierze wiersze zaczynające się znakiem c lub d.
Polecenie
grep "^c\|^d" /etc/termcap
da dokładnie ten sam wynik jednak znak OR czyli | trzeba zamaskować lewym ukośnikiem.
Maskowanie znaków
Przy używaniu grepa trzeba maskować następujące znaki: + | { } ( ) ?
Nie musimy tego robić gdy użyjemy opcji -E.