Search
Regulární výraz je textový vzor reprezentující množinu řetězců, využitý pro vyhledávání, extrakci, nebo nahrazení v textu.
Regulární výraz je řetězec skládající se z běžných znaků (např. písmena a číslice) a tzv. metaznaků. Metaznaky jsou znaky se zvláštním významem, umožňující reprezentovat množinu znaků. Jedná se o znaky
^ $ . + ? * { [ () | \
Používá se více různých specifikací regulárních výrazů, přičemž často používané jsou
Dále jsou popsány regulární výrazy dle normy POSIX, běžně používané nástroji dostupnými v unixových systémech.
Pokud má být metaznak interpretován jako běžný znak (bez zvláštního významu), musí být uveden za znakem zpětného lomítka (\).
fel\.cvut\.cz # odpovídá řetězci "fel.cvut.cz"
Nejobecnějším metaznakem je tečka (.), reprezentující jeden libovolný znak. Regulární výraz
a.c
Metaznak . je v mnoha případech příliš obecný a potřebovali bychom omezit množinu reprezentovaných znaků. Množinu reprezentovaných znaků zapisujeme do hranatých závorek. Následující výraz reprezentuje řetězce “ade”, “bde” a “cde”.
[abc]de
[a-z] # jakékoliv malé písmeno anglické abecedy [0-9] # jakákoliv číslice [A-Za-z0-9] # jakýkoliv alfanumerický znak (kromě znaků národních abeced)
[^A-Za-z] # jakýkoliv znak kromě písmen anglické abecedy
Pro často používané množiny znaků jsou připraveny třídy znaků, zapsané jako [[:classname:]], např.
[[:blank:]] mezera nebo tabulátor [[:space:]] mezery specifikované v "C locale" (space, tab, new line, form feed, carriage return) [[:alpha:]] všechna písmena (včetně znaků národní abecedy) [[:alnum:]] alfanumerické znaky [[:digit:]] číslice (stejné jako [0-9]) [[:lower:]] malá písmena
Kvantifikátory umožňují reprezentovat opakující se výrazy. Jedná se o postfixové operátory, které mají vliv na předcházející znak:
a* libovolné opakování znaku "a" (vč. prázdného řetězce) a\+ libovolné opakování znaku "a" (alespoň 1 výskyt) a\? znak "a" nebo prázdný řetězec a\{3\} znak "a" opakující se 3x a\{3,5\} znak "a" opakující se 3-5x
Kvantifikátory mají vliv na bezprostředně předcházející znak. Pokud mají být aplikovány na delší výraz, je možné uzavřít tento podvýraz do závorek:
[0-9]\+\(,[0-9]\+\)* libovolně dlouhý seznam čísel oddělených čárkou (bez jakýchkoliv mezer)
[0-9]+(,[0-9]+)*
Závorky mohou mít další význam, podle použitého nástroje. Nástroje pro vyhledávání a náhradu textu umožňují vložit část původního textu, odpovídající výrazu v závorce do výsledného nahrazujícího textu, vložením zpětného lomítka a pořadového čísla příslušné závorky v hledaném výrazu. Některé nástroje pro vyhledávání textu umožňují extrahovat části textu odpovídající závorkám pro další využití (např. přiřadit je do samostatných proměnných).
Znakem roura (|) je možné specifikovat alternativy. V základních výrazech je nutné znak | psát za zpětné lomítko.
color\|colour colo\(r\|ur\)
Kotvy je možné použít ke specifikaci začátku nebo konce slova nebo řádky uvnitř výrazu. Tyto metaznaky nezastupují žádný konkrétní znak, ale pouze označují rozhraní mezi znaky slova a jinými znaky. Kotvy definované specifikací POSIX zahrnují:
\< začátek slova \> konec slova ^ začátek řádky $ konec řádky
Příklady použití:
\<word\> reprezentuje "word", ale ne "words" \<a[a-z]* reprezentuje jakékoliv slovo začínající na "a" napsané malými písmeny ^From: reprezentuje začátek řádky začínající řetězcem "From:" ^[a-zA-Z0-9_]\+$ reprezentuje pouze text složený z alfanumerických znaků a podtržítek, žádné jiné znaky nesmí být před ani za korespondujícím textem
Specifikace regulárních výrazů podle normy POSIX je dostupná v manuálových stránkách:
man 7 regex
Regex tutorial by Mira Bursa
Skriptovací jazyk bash umožňuje ověřovat, zda řetězec obsahuje podřetězec odpovídající regulárnímu výrazu, následující konstrukcí:
if [[ "$var" =~ a[0-9] ]] ; then ... if [[ "$a" =~ ^[[:digit:]]+$ ]] ; then echo "${a} is a number" fi
Povšimněte si použití dvojitých hranatých závorek (narozdíl od volání příkazu test). Dále pamatujte na to že regulární výrazy se neuzavírají do uvozovek (od bashe ver. 3.2, uvozovky by byly chápány jako součást výrazu).
V proměnné BASH_REMATCH navíc bash poskytuje text odpovídající zadanému výrazu.
Pokud potřebujete napsat skript zaměřený na zpracování textu, zvažte použití skriptovacího jazyka Perl, který má řadu vestavěných funkcí pro zpracování textu a podporu regulárních výrazů.
https://www.perl.org/
Nástroj grep prohledává vstupní text a hledá řádky odpovídající zadanému regulárnímu výrazu a tyto řádky tiskne na výstup. Ostatní řádky jsou zahozeny. Grep zpracovává text ze souboru, který je zadán jako parametr, nebo text ze standardního vstupu.
Příklad: (nalezení řádků obsahujících direktivu #include ve zdrojovém souboru jazyka C)
grep '^[[:space:]]*#include[[:space:]]*[<"][^>"]*[>"]' source_file.c
Příklad: (nalezení všech souborů v adresáři se jménem délky alespoň 3 znaky)
ls | grep '^....*$'
Grep podporuje jak základní tak rozšířené regulární výrazy (pokud je použit přepínač -E). Další užitečné přepínače jsou:
-i (ignorace velikosti písmen při vyhledávání) -v (vyhledávání řetězců, které neodpovídají výrazu) -c (tisk počtu odpovídajících řádek, místo obsahu řádek) -o (tisk pouze částí řádek odpovídajících výrazu) -n (tisk čísla řádky před každou nalezenou řádku)
Jediným voláním příkazu je možné prohledat více souborů, nebo celou adresářovou strukturu.
AWK je interpretovaný programovací jazyk navržený pro zpracování textu. Program v jazyce AWK sestává z dvojic vzor-akce, zapsaných jako
vzor { akce }
Příklad: tisk vlastníků souborů v pracovním adresáři
ls -l | awk '{ print $3 }'
Jazyk AWK poskytuje další vnitřní proměnné:
NR (number of records) -- číslo aktuálně zpracovávaného řádku NF (number of fields) -- počet sloupců aktuálního řádku FS (field separator) -- znak použitý jako oddělovač sloupců
Vzory mohou mít podobu regulárního výrazu:
/pattern/ { action } # všechny řádky odpovídající výrazu "pattern"
NR=10 { action } # akce se vykoná pro 10. řádku
( $3 == "string" && NR>10 ) || NR == 1 { action } ! /pattern/ { action } # negace -- všechny řádky neodpovídající výrazu "pattern"
END { print NR } # tisk počtu řádek vstupního textu
Nejčastěji používaným příkazem v akcích je příkaz print. Alternativně je možné použít příkaz printf pro formátovaný výstup, jehož syntaxe je podobná jako u stejnojmenné funkce jazyka C.
V rámci vzorů i akcí mohou být použity vestavěné funkce. K dispozici jsou numerické funkce (např. sqrt, sin, exp), nebo řetězcové funkce, např.
length(str) # délka řetězce index(string, substring) # poloha podřetězce v řetězci substr(string, position [, length]) # extrakce podřetězce z řetězce match(string,regex) # test zda řetězec odpovídá regulárnímu výrazu tolower(string) # konverze řetězce na malá písmena
AWK podporuje řetězcové a numerické proměnné a asociativní pole. Umožňuje také definovat uživatelské funkce.
Výchozí oddělovač sloupců (sekvence mezer a podobných znaků) může být změněn přepínačem -F:
awk -F':' '{ print $1 " " $3 }' /etc/passwd
Program v jazyce AWK může být napsán v samostatném souboru, nebo jako argument příkazu awk:
awk -f script.awk input_file.txt awk '/pattern/ { print $0 }' input_file.txt
awk čte text ze souboru zadaného jako parametr, nebo ze standardního vstupu, není-li soubor zadán.
awk '/pattern/ { print $0 }' input_file.txt cat input_file.txt | awk '/pattern/ { print $0 }'
GNU awk User's Guide
sed je mocný a efektivní nástroj pro transformaci textu, který na řádky vstupního textu aplikuje příkazy ve vlastním jazyce. Vstupní text je načítán ze zadaného souboru, nebo ze standardního vstupu.
Mezi základní příkazy sedu patří
a append - vložení textu za zpracovávaný blok textu i insert - vložení textu před zpracovávaný blok textu q quit - ukončení skriptu a zpracování r připojení textu z externího souboru c change - přepsání zpracovávaného bloku jiným textem d delete - mazání řádek textu h hold - uložení řádek do odkládací paměti (hold space) g vložení řádek z odkládací paměti na aktuální pozici s/regexp/replacement/ nahrazení řetězců odpovídajících regulárnímu výrazu jiným řetězcem
V praxi se nejčastěji používá příkaz s, tedy nahrazení textu jiným textem.
s
Většina příkazů může mít specifikovanou adresu určující na které řádky se má příkaz aplikovat. Adresa se píše bezprostředně před příkaz. Příkazy bez adresy jsou aplikovány na všechny vstupní řádky. Adresa může mít podobu
Vykřičník (!) mezi adresou a příkazem invertuje vzor, tzn. aplikuje příkaz na všechny řádky, které vzoru/adrese neodpovídají.
Skript v jazyce sed je možné číst ze samostatného souboru, nebo z argumentu:
sed -f sed_script input_data.txt sed -e '1d' input_data.txt
1,3d # smaž první 3 řádky 25h 36g # zkopíruj řádku 25 do paměti a vlož ji na pozici řádky 36 /[0-9]/d # smaž všechny řádky obsahující číslice 3a hello # vlož řádku "hello" za třetí řádku s/[^a-zA-Z0-9 ]*/_/g # zaměň všechny sekvence nealfanumerických znaků podtržítkem
sed, a stream editor
tr je jednoduchý program, který čte ze standardního vstupu a zapistuje na standardní výstup a umí změnit jednotlivé znaky za jiné či je mazat. Příkaz
tr abc def
zamění a za d, b za e atd. Příkaz
a
d
b
e
tr -d '\n'
smaže všechny znaky konec řádky.