Łukasz Borchmann

Polecenie grep służy do wyszukiwania w tekście z zastosowaniem wyrażeń regularnych, czyli formalizmu, który pozwala poszukiwać pewnych wzorców. Formalizm ten ma szerokie zastosowanie i jego poznanie będzie przydatne w wielu innych przypadkach, zaś najłatwiej zrozumieć go (i o co chodzi) na przykładach.

Przyjmijmy, że dysponujemy plikiem slowoformy.txt, stworzonym zgodnie z opisem w poprzedniej części notatek. Przypomnijmy, że zawiera on wszystkie słowoformy poświadczone w słowniku gramatycznym języka polskiego.

Początek i koniec lub ich brak

Jednymi z najprostszych operacji przeszukiwania, jakich możemy dokonać są:

Pierwsza z nich zwróci wszystkie słowa zawierające wewnątrz ciąg „nie”, np. niemiły, skomlenie czy najabsurdalniejszemu. Znak ^ w wyrażeniach regularnych oznacza początek, zaś $ – koniec, dlatego:

  • przykład z drugiej linii zwróci wyłącznie słowa rozpoczynające się od „nie” (takie jak niemiły, nie, niemowa i niechęć),
  • wyrażenie nie$ spowoduje wyfiltrowanie słowoform kończących się na „nie” (np. absurdalnie, nie, ćpanie),
  • ostatni przykład znajdzie słowa, dla których między początkiem a końcem znajduje się wyłącznie ciąg „nie”, czyli wyłącznie słowo nie.

Dowolny znak oraz wybrana liczba powtórzeń

Kropka ( .) w wyrażeniach regularnych wykorzystywana jest do oznaczenia dowolnego znaku. Łącząc tę informację z podanymi wyżej wypróbować możemy komendy do wyszukiwania słów rozpoczynających się na „nie”, a składających się kolejno z czterech (np. nieś, niej), pięciu (niego, nieuk) i sześciu znaków (niezłe, nietyć):

W tym miejscu wprowadźmy opcję E (od extended), która ze względu na pewne niegodne uwagi zaszłości historyczne jest wymagana do obsługi niektórych wyrażeń regularnych. Dobrze o niej pamiętać, kiedy pieczołowicie opracowane przez nas wyrażenie regularne nie będzie zwracało żadnych wyników… Od tego momentu wszystkie wywołania polecenia grep zawierać będą opcję E, nawet jeśli nie jest ona wymagana dla prawidłowego funkcjonowania wyrażenia.

Porzucając przykłady z „nie” i uwagi na temat pewnej udziwniającej opcji, wyszukać moglibyśmy po prostu słowa dziesięcioliterowe (np. czasownika, ezoteryków). Można to zrobić na sposób analogiczny do powyższego (powielając dziesięciokrotnie znak kropki) lub ekonomiczniej – stosując nawiasy klamrowe, a w nich wymaganą liczbę powtórzeń (poniższe komendy są tożsame):

Nawias klamrowy stosuje się do dowolnego znaku znajdującego się przed nim (tutaj kropki), tak więc wyrażenia ^aa oraz ^a{2} są tożsame i pozwolą odnaleźć słowa rozpoczynające się na „aa”, takie jak aaronowemu.

W nawiasach klamrowych podać możemy nie tylko dokładną liczbę powtórzeń danego znaku, ale również przedział. W poniższych przykładach wyszukujemy kolejno: słów od 3 do 5 znaków, słów od 6 do 11 znaków oraz słów składających się z 4 lub więcej znaków (po przecinku celowo nie podano drugiej wartości, co oznacza właśnie brak górnego limitu).

Określone klasy (zbiory) znaków

Jednym ze sposobów na wyfiltrowanie jednym wyrażeniem słów rozpoczynających się na literę „a” lub literę „b” jest użycie klasy znaków, którą zapisujemy z zastosowaniem nawiasów kwadratowych:

Linie 1. i 2. są tożsame (kolejność znaków w nawiasie kwadratowym nie ma znaczenia). W linii 3. uwzględniono w wyszukiwaniu słowa, które zaczynają się wielkimi literami (domyślnie grep, jak to niektórzy ujmują, „rozróżnia semantykę liter małych i wielkich”, tj. jest case-sensitive). Linie 3. i 4. są tożsame – w tej drugiej zastosowano opcję i, która wyłącza czułość na wielkość liter (tak, że komenda staje się case-insensitive).

Nie musimy jednak wymieniać jeden po drugim wszystkich znaków, które chcemy dopuścić, ale zastosować można pewne uproszczenia zapisu i tak:

  • [A-Z] oznacza wszystkie wielkie litery alfabetu łacińskiego (ale już nie polskie znaki opatrzone diakrytem),
  • [a-z] jest tożsame z wymienieniem w tym nawiasie wszystkich małych liter alfabetu łacińskiego,
  • [0-9] jest identyczne z [0123456789] i dopuszcza każdą cyfrę,
  • [A-Za-z] oznacza wszystkie (wielkie i małe) litery łacinki,
  • [a-ząćęłńóśżź] to klasa obejmująca wszystkie małe litery polskiego alfabetu (co można zapisać nieco prościej, o czym w przyszłości).

Poniższe przykłady przedstawiają kolejno wyszukiwanie słów rozpoczętych wielką literą alfabetu łacińskiego oraz wyrazów rozpoczętych wielką literą alfabetu łacińskiego, które liczą co najmniej pięć znaków.

Zastosowanie po otwarciu nawiasu kwadratowego symbolu ^ oznacza wyłączenie zdefiniowanych w nim znaków, np. wyszukując ^[^ab] znajdziemy słowa, które nie rozpoczynają się ani literą „a”, ani literą „b”. Podobnie, w poniższym przykładzie wyszukamy słowoformy, które nie rozpoczynają się wielką literą alfabetu łacińskiego (linia 1.) oraz wyrazy nierozpoczęte wielką literą alfabetu łacińskiego, które liczą co najmniej pięć znaków (2).

Symbol gwiazdki, plusa i pytajnika

Gwiazdkę ( *, plus ( +) i znak zapytania ( ?) traktować można jako synonimy szczególnych przypadków nawiasów klamrowych, o których była mowa wyżej.

Pierwszy z symboli oznacza dowolną liczbę powtórzeń znaku (czyli np. .* oznacza dokładnie to samo, co .{0,}), zaś drugi – liczbę powtórzeń większą niż jeden (tak więc zarówno [a-z]+, jak i [a-z]{1,}, to przynajmniej jedna mała litera alfabetu łacińskiego). Za znakiem zapytania kryje się zero lub jedno powtórzenie, a zatem [0-9]{0,1}, jak i [0-9]?, to dowolna cyfra arabska lub jej brak.