Regulární výrazy a grep

Jak už víte z dřívějška, grep umí různě filtrovat řádky podle vzorů. A tím vzorem může být kromě slova i regulární výraz. Pomocí něj můžete velmi přesně specifikovat to, co se má filtrovat.

Předpokládám, že zástupné znaky již znáte, včetně možnosti na určitém místě specifikovat rozsah znaků, které se mají vybrat, pomocí hranatých závorek. A třeba právě to je také regulární výraz.

Něco takového už by vám tedy mělo být jasné:

  [Aa]hoj

Tomuto výrazu vyhoví jak ahoj, tak Ahoj. V hranatých závorkách jste specifikovali, že na prvním místě může být velké nebo malé A. V regulárních výrazech máte ale k dispozici další zástupné a speciální znaky (viz tabulka níže). Cokoliv mimo těchto zástupných znaků bude interpretováno jako text, který se musí vyskytovat v příslušném řetězci, aby ten odpovídal regulárnímu výrazu.

Znak(y) Význam
. tečka zastupuje jeden libovolný znak
[] hranaté závorky zastupují jeden znak, který musí odpovídat některému ze znaků uvnitř hranatých závorek
^ začátek řádku
$ konec řádku
? předchozí znak je nepovinný a smí se nacházet v daném výrazu nejvýše jednou
* libovolný počet opakování předchozího znaku (včetně nulového opakování, tj. situaci, kdy se znak na daném místě nenachází)
+ předchozí znak se musí vyskytovat alespoň jednou nebo vícekrát
{n} předchozí znak se musí vyskytovat n krát
{n,} předchozí znak se musí vyskytovat n nebo více krát
{,m} předchozí znak se musí vyskytovat nejvýše m krát
{n,m} předchozí znak se musí vyskytovat nejméně n krát a nejvíce m krát
| roura je logickou spojkou nebo, tj. umožňuje specifikovat více regulárních výrazů, přičemž filtrovaný řetězec bude propuštěn, pokud vyhoví kterémukoliv z nich

Jakkoliv složitě to vypadá, je to vlastně docela jednoduché. Podívejme se na několik příkladů, na kterých si vše objasníme. Začneme tímto výrazem:

  ^[A-Z]hoj$

Znaky ^ a $ označují začátek a konec řádku. Tento regulární výraz tedy propustí pouze ty řádky, které začínají jedním velkým písmenem, pokračují textem hoj a tím končí.

  ^[0-9A-Za-z]{5}$

Tomuto regulárnímu výrazu odpoví jakákoliv řádka, na které je pouze pět znaků, a to z alfanumerické množiny (velká a malá písmena, čísla).

  michal|jana

Tomuto regulárnímu výrazu odpoví jakýkoliv řetězec, ve kterém se nachází michal nebo jana. Znakem roury jsme spojili dva regulární výrazy do jednoho, kterému odpovídá jakýkoliv řetězec, který vyhovuje kterémukoliv z těchto dvou regulárních výrazů.

  [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}

Tento regulární výraz propustí jakýkoliv řetězec obsahující IP adresu. Přesněji jakýkoliv řetězec, který obsahuje jedno až tři čísla, tečku (zpětným lomítkem jsme neutralizovali její vliv jako zástupný znak pro jeden libovolný znak), jedno až tři čísla, další tečku, jedno až tři čísla, tečku a jedno až tři čísla.

Dlužno dodat, že tomuto výrazu bude odpovídat i nesmyslná IP adresa jako třeba tato:

  945.847.654.425

Pokračujme dál:

  ah.*oj

Tento regulární výraz bude odpovídat všem řetězcům, kde se nachází ah, libovolný počet libovolných znaků a oj.

Grep a regulární výrazy

Regulární výrazy v grepu se zadávají malinko jinak, než jsme si ukázali. Respektive, abyste mohli pracovat s regulárními výrazy tak, jak jste na ně zvyklí, museli byste použít takovýto příkaz:

  echo -e "miii\nmooo" | grep -E "mi{3}|mo{3}"

Ten by pak vrátil následující:

  miii
  mooo

Tohle si opět podrobně vysvětlíme. Volbou -e programu echo jsme povolili interpretaci speciálních znaků uvozených zpětným lomítkem. Takovým znakem je třeba \n, který se pak interpretuje jako odentrování (tj. znak nového řádku). Tento zápis tedy vytvoří dva řádky, jeden s obsahem miii a druhý s obsahem mooo.

Regulární výrazy jsou spojeny rourou, takže vyhoví obě řádky. Jedna vyhoví prvnímu výrazu, druhá druhému. Grepu bylo třeba parametrem -E říci, aby daný výraz interpretoval jako rozšířený regulární výraz. To je takový, na který jsme si dosud zvykli. Bez tohoto parametru interpretuje grep (a také třeba sed a další programy) pouze „základní“ regulární výrazy. To jsou takové, kde místo speciálních znaků regulárních výrazů použijete jejich ekvivalenty se zpětným lomítkem, jako byste chtěli neutralizovat jejich význam.

Výše zmíněný výraz bychom pro standardní grep tedy museli přepsat do této podoby:

  mi\{3\}\|mo\{3\}

Vypadá to sice hrozivě, ale pokud víte, že před každý ze speciálních znaků regulárních výrazů napíšete zpětné lomítko, není to až takový problém.

Kam dál

pokrocili/komandlajna/regexp_grep.txt · Poslední úprava: 2009/11/11 14:38 autor: Michal Dočekal
CC Attribution-Share Alike 3.0
www.chimeric.de Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0 PDF Export