Poznamy teraz kilka narzędzi ułatwiających codzienną pracę z plikami zawierającymi teksty. Przydatne są one zwłaszcza wtedy, gdy pracujemy z większą liczbą plików.
Często zdarza nam się poszukiwać pliku, zawierającego pewien charakterystyczny fragment tekstu. Służy do tego rodzina poleceń fgrep, grep i egrep. Pozwalają one wyszukiwać pliki, zawierające wiersze o wskazanej postaci. Pierwszym argumentem polecenia fgrep powinien być napis, którego szukamy. W najprostszym przypadku może to być pojedyncze słowo. Pozostałe argumenty opisują pliki do przeszukania.
$ ls postacie przybysze wszyscy zwrotka $ cat zwrotka Hejże ha! Niech Kubuś żyje! Niechaj tyje, je i pije! Czy przy środzie, czy przy wtorku, On w miodowym jest humorku. I niewiele o co dba, Gdy na nosie miodek ma! Więc śpiewajcie wszyscy dzisiaj Hymn na cześć Puchatka-Misia Który swe Conieco zje Za godzinę lub za dwie! $ fgrep Kubuś zwrotka Hejże ha! Niech Kubuś żyje! $ fgrep Kubuś * postacie: Kubuś Puchatek wszyscy: Kubuś Puchatek zwrotka: Hejże ha! Niech Kubuś żyje! $ _
Polecenie fgrep wypisuje wszystkie linie zawierające poszukiwany napis. Jeśli przeszukiwaliśmy kilka plików to każda linia poprzedzana jest nazwą pliku, z którego pochodzi. Może się zdarzyć, że poszukiwany tekst zawiera znak służący do rozdzielania argumentów polecenia. Takim znakiem jest na przykład spacja. Musimy wtedy otoczyć tekst cudzysłowami.
$ fgrep "Kubuś Puchatek" * postacie: Kubuś Puchatek wszyscy: Kubuś Puchatek $ _
Przy bardziej skomplikowanym przeszukiwaniu polecenie fgrep przestaje wystarczać. Musimy posłużyć się poleceniami grep lub egrep, używającymi wyrażeń regularnych. Warto zapoznać się z wyrażeniami regularnymi, ponieważ oprócz występowania w argumentach poleceń wyszukiwania wykorzystywane są one w edytorach.
Wyrażenia regularne przypominają budową wzorce nazw plików, różnią się jednak od nich przeznaczeniem. Zadaniem ich jest opisywanie dowolnych napisów. Budowane są na podobnej zasadzie, ale inny nieco jest repertuar metaznaków i spełniane przez nie funkcje. Metaznakiem pasującym do dowolnego pojedynczego znaku jest kropka.
$ grep "Niech." zwrotka Hejże ha! Niech Kubuś żyje! Niechaj tyje, je i pije! $ _
Odszukane zostały linie, zawierające pasujące napisy ,,Niech '' oraz ,,Niecha''. Należy pamiętać, aby wyrażenia regularne otaczać cudzysłowami. W tym przypadku nie miało to akurat znaczenia, ale inne metaznaki mogą zostać przetworzone przez interpreter poleceń.
Aby ułatwić sobie orientację w wyszukiwanych liniach warto skorzystać z opcji -n, dzięki której wypisywane linie poprzedzane są numerem podającym ich pozycję w pliku.
$ grep -n "z. " zwrotka 3: Czy przy środzie, czy przy wtorku, 11: Za godzinę lub za dwie! $ grep
Inna pożyteczna opcja to -v, odwracająca działanie polecenia grep. Po jej otrzymaniu polecenie grep wyszuka wszystkie linie nie pasujące do podanego wyrażenia, na przykład nie zawierające podanego napisu. Poszukajmy linii nie zawierających wykrzyknika.
$ grep -v "!" zwrotka Czy przy środzie, czy przy wtorku, On w miodowym jest humorku. I niewiele o co dba, Więc śpiewajcie wszyscy dzisiaj Hymn na cześć Puchatka-Misia Który swe Conieco zje $ _
Spróbujmy teraz odnaleźć wszystkie linie, w których występują czteroliterowe słowa rozpoczynające się literą p.
$ grep -n "p..." zwrotka 2: Niechaj tyje, je i pije! 3: Czy przy środzie, czy przy wtorku, 8: Więc śpiewajcie wszyscy dzisiaj $ _
Wynik jest częściowo poprawny. Otrzymaliśmy obie poszukiwane linie oraz jedną zbędną. Zmodyfikujmy nieco nasz wzorzec, aby wykluczyć zbyt długie słowa.
$ grep -n " p... " zwrotka 3: Czy przy środzie, czy przy wtorku, $ _
Tym razem wykluczyliśmy za dużo. Brakującą linię można by odszukać wywołując drugi raz polecenie grep z argumentem ,,p....!''. Lepiej jednak wykorzystać klasy znaków.
Skorzystamy teraz z nawiasów kwadratowych, które w wyrażeniach regularnych podobnie jak we wzorcach nazw plików służą do zapisywania klas znaków.
$ grep -n " p...[ !]" zwrotka 2: Niechaj tyje, je i pije! 3: Czy przy środzie, czy przy wtorku, $ _
Klasy często stosuje się do utożsamiania dużych i małych liter przy wyszukiwaniu.
$ grep "[Nn]ie" zwrotka1 Hejże ha! Niech Kubuś żyje! Niechaj tyje, je i pije! I niewiele o co dba, Który swe Conieco zje $ _
Ten sam efekt można było osiągnąć używając opcji -i, wymuszającej ignorowanie pocztu liter.
$ grep -i "nie" zwrotka1 Hejże ha! Niech Kubuś żyje! Niechaj tyje, je i pije! I niewiele o co dba, Który swe Conieco zje $ _
Przypomnijmy sobie jeszcze rolę myślnika przy zapisywaniu klas.
$ grep "[a-z]nie" zwrotka Który swe Conieco zje $ _
W wyrażeniach regularnych oprócz wybierania znaków z pewnej klasy możemy zażądać unikania znaków z pewnej klasy. Jeśli pierwszym znakiem (pomijając początkowy nawias) w zapisie klasy jest ^, to klasę taką nazywamy zanegowaną. Klasa zanegowana pasuje do dowolnych znaków nie występujących w klasie.
$ grep "[^Nn]ie" zwrotka I niewiele o co dba, Gdy na nosie miodek ma! Więc śpiewajcie wszyscy dzisiaj $ _
Klasa zanegowana przydaje się do lepszego zapisania granic słowa.
$ grep "[^a-zA-Z]p...[^a-zA-Z]" zwrotka 2: Niechaj tyje, je i pije! 3: Czy przy środzie, czy przy wtorku, $ _
Metaznaki ^ i $ umożliwiają ograniczenie wyszukiwania do napisów znajdujących się na początku względnie końcu linii. Jeśli ^ jest pierwszym znakiem wyrażenia regularnego, to szukany tekst musi znajdować się na początku linii.
$ grep "^Niech" zwrotka Niechaj tyje, je i pije! $ _
Pierwsza linia nie została odszukana, gdyż napis ,,Niech'' występuje w niej w środku linii. Metaznak $ spełnia analogiczną rolę pod warunkiem, że występuje na końcu wyrażenia. Tekst zostanie odszukany tylko wtedy, gdy wystąpi na końcu linii.
$ grep "je$" zwrotka Który swe Conieco zje $ _
Używając poznanych przed chwilą metaznaków można wyszukać w tekście puste linie.
$ grep -n "^$" zwrotka 7: $ _
Czasami szukany fragment tekstu zawiera znaki specjalne. Tak będzie przy szukaniu linii kończących się kropką. Podanie wzorca .$ spowodowałoby wypisanie wszystkich niepustych linii. Aby zapobiec specjalnemu potraktowaniu znaku należy go poprzedzić odwrotnym ukośnikiem (\). Służy on więc do przesłaniania następującego po nim metaznaku.
$ grep "\.$" zwrotka On w miodowym jest humorku. $ _
Pokazaliśmy powyżej, jak odszukać puste linie. Czasem jednak taka linia może zawierać znaki niewidoczne -- najczęściej spacje lub znaki tabulacji. Stosując podane poprzednio wyrażenie nie zostałyby one odszukane. Jak jednak powiedzieć: ,,kilka spacji''?
Wyrażenie służące do opisu ciągu jednakowych znaków nazywamy domknięciem. Składa się ono z dowolnego elementu, po którym stoi metaznak *, na przykład a* oznacza ciąg liter 'a' dowolnej długości (może to być pusty ciąg, co wykorzystamy za chwilę).
Teraz już możemy odszukać linie zawierające wyłącznie znaki niewidoczne. Uwaga: wewnątrz nawiasów kwadratowych znajdują się znaki spacji i tabulacji.
$ grep -n "^[ ]*$" zwrotka 7: $ _
Powyższe wyszukiwanie obejmuje również całkowicie puste linie, dlatego efekt jest ten sam co poprzednio. Zwróćmy uwagę na inną funkcję metaznaku * w wyrażeniach regularnych niż we wzorcach nazw plików.
Na koniec spróbujmy odszukać linie, zaczynające się i kończące literą.
$ grep "^[A-Za-z].*[A-Za-z]$" zwrotka Więc śpiewajcie wszyscy dzisiaj Który swe Conieco zje $ _