Регулярни изрази за търсене във файлове, egrep
2. Търсене във файлове с egrep
3. Съвпадения на шаблони (pattern matching)
Регулярният израз (regular expression или regex) представлява текстов шаблон (pattern) , който се използва от команди като grep, egrep, sed (stream editor for filtering and transforming text), awk (scripting language used for manipulating data and generating reports), езици като Perl, Javascript и много други приложения за откриване на "текстов низ" (string of text) във файл. Под "текстов низ" се разбира символ, дума, изречение или специален шаблон (pattern) от символи. Използва се програма (regular expression engine) за транслиране на шаблона при сравняване с обработвания текст.
Unix/Linux използва два
вида regular expression engine:
Повечето Unix/Linux програми работят с BRE, но има и много, които ползват ERE.
Тъй като има много regex реализации, в настоящата глава ще бъдат разгледани само на-често използваните и ще бъдат демонстрирани с командата egrep (или grep -E), която е акроним на "Extended Global Regular Expressions Print".
Командата egrep извежда в stdout всички редове, които съответстват на даден шаблон (pattern), зададен като първи параметър на командата, намерени в stdin (или от файловете зададени като останалите параметри на командата).
$ egrep [command line options] <pattern> [<filename>]
Някой често използвани опции:
· -i прави търсенето да не различава малките и главните букви.
· -r търси рекурсивно в файлове в специфицираните директории.
· -l извежда само имената на анализираните файлове , които съдържат търсения шаблон.
· -c извежда броя на съвпаденията.
· -n номерира анализираните редове.
· -v обръща теста – извежда редовете без съвпадения.
Например за извеждане на екрана (stdout) всички редове въведени от клавиатурата (stdin ), които съдържат низа aha командата се подава без опции с "aha" като шаблон и без втори параметър:
$ egrep "aha"
rty
ahasd
ahasd
rahat
rahat
^D
$
Ако бъде подадена опция -c:
$ egrep -c "aha"
rty
ahasd
rahat
^D
2
$
Ако бъде подадена опция -n
$ egrep -n "aha"
rty
ahasd
2:ahasd
rahat
3:rahat
^D
$
Нека файлът regex.txt да съдържа ( може да бъде
създаден например с cat или с редактор nano) :
$ cat > regex.txt
egrep stands for:
extended
global
regular
expression
print
$
Файлът може да бъде претърсен за редове съдържащи някакъв символ или низ от символи. Например за извеждане на екрана на всички редове от файла съдържащи символа 't' :
$ egrep "t" regex.txt
egrep stands for:
extended
print
$
За извеждане на редовете съдържащи (или не) низа 'ex' :
$egrep -n "ex" regex.txt
2:extended
5:expression
$ egrep -nv "ex" regex.txt
1:egrep stands for:
3:global
4:regular
6:print
$
Командата egrep се използва както за намиране на прости низове, така и на шаблони.
Шаблоните се задават с регулярни изрази (regular expressions, regex). Регулярните изрази се използват за описание на множество от низове и се състоят от обикновени символи и от мета-символи със специално значение (операции). Метасимволите са:
.*[]^${}\+?|()
Така например, ако се използва метасимволът ^ в началото на низа, то търсенето на символ или низ се ограничава само до началото на линията:
$ egrep "^g" regex.txt
global
$
Ако мета-символ трябва да се търси като обикновен символ, той трябва да се предшества от "escape" - '\':
$ egrep "\^g"
gkpp
ssss^gjjj
ssss^gjjj
$
Метасимволът $ зададен в края на низа го задължава да се намира в края на линията:
$ egrep "t$" regex.txt
print
$
Метасимволът точка . замества произволен символ. Така например 'a.c' описва множеството от низове "abc", "akc", "a-c", … (но не и "ac")!
$ egrep "a.c"
abc
abc
akc
akc
ac
$
Вертикална черта | задава алтернативи. Така например 'gray|grey' и описва множеството от низове "gray" и "grey".
Малки скоби се използват за описване област на действие и подреждане на низовите последователности.
Например 'gray|grey' и 'gr(a|e) y' са еквивалентни.
Пример: Сравнете "gr(a|e)y" и "gra|ey"
Средни скоби се използват за изграждане на символен клас ( един символ зададен с алтернативи от символи). В съвпадението участва всеки единичен символ от класа, а последователност от символи се задава с три символа: първи и последен символ свързани със средно тире. Обикновените символи и последователностите могат да се смесват.
Например 'gr[aep-s]y' и 'gr(a|e|p|q|r|s) y' са еквивалентни.
Тирето в началото или в края на средните скоби е обикновен символ:. [-ab] , [ab-]
$ egrep "k[-ab]r"
kar
kar
ker
kbr
kbr
k-r
k-r
kr
$
Символите точка (".") и вертикална черта ("|") в средни скоби са обикновени, а не метасимволи.
$ egrep "k[.|a-]"
k.
k.
k|
k|
ka
ka
k-
k-
ke
$
Символът ^ поставен в началото на средни скоби замества произволен символ, който не се съдържа в скобите. Следващият пример извежда от текста за лиценза GPL-3 всички линии съдържащи четирибукви, завършващи на "ode" - "mode", "modelisation", "lode", "Code" ..., но не и "code":
$ egrep "[^c]ode"
/usr/share/common-licenses/GPL-3
1. Source Code.
model,
to give anyone who possesses the object code either (1) a
the only significant mode
of use of the product.
notice like this when it starts in an interactive mode:
$ egrep -n "[^c]ode"
/usr/share/common-licenses/GPL-3
112: 1. Source Code.
261: model,
to give anyone who possesses the object code either (1) a
308:the only significant mode
of use of the product.
653:notice like this when it starts in an interactive mode:
$
Квантификатор зададен след символ или група специфицира колко пъти този елемент може да се появи. Най-честите квантификатори са въпросителна ?, звезда * и символът + .
? 0 или една поява на предходния елемент. Например 'colou?r' дефинира множеството "color" и "colour".
* 0 или повече повторения на предходния елемент. Например 'ab*c' дефинира множеството "ac", "abc", "abbc", "abbbc" ...
Ако трябва да се изведат всички линии от текста за лиценза GPL-3, които съдържат отваряща и затваряща скоба, а между тях - само латински букви и интервали:
$ egrep "\(([A-Za-z ]*)\)"
/usr/share/common-licenses/GPL-3
Copyright (C) 2007
Free Software Foundation, Inc. <http://fsf.org/>
distribution (with or without
modification), making available to the
than the work as a whole, that (a)
is included in the normal form of
Component, and (b) serves
only to enable use of the work with that
(if any) on which the
executable work runs, or a compiler used to
...
+ 1 или повече повторения на предходния елемент. Например 'ab+c' задава "abc", "abbc", "abbbc"…, но не и "ac".
{n} Предходния елемент се среща точно n пъти. Например '[0-9]{2}' означава комбинация от 2 цифри.
{min,} Предходния елемент се среща min или повече пъти.
{min,max} Предходния елемент се среща най-малко min пъти, но не повече от max пъти..
Командата egrep работи с разширени (extended) регулярни изрази и е еквивалентна на командата grep –E. При команда grep символите ?, +, {, |, (, и ) се третират като нормални символи. За да бъдат считани за метасимволи трябва да бъдат предшествани от обратна наклонена черта: \?, \+, \{, \|, \(, и \).
Нека да бъде създаден текстов файл test_regex
$ cat > test_regex
Fred apples 20
Susy oranges 5
Mark watermellons 12
Robert pears 4
Terry oranges 9
Lisa peaches 7
Susy oranges 12
Mark grapes 39
Anne mangoes 7
Greg pineapples 3
Oliver rockmellons 2
Betty limes 14
$
Да се изведат линиите съдержащи mell:
$ egrep 'mell' test_regex
Mark watermellons 12
Oliver rockmellons 2
$
За извеждане номерата на линиите:
$ egrep -n 'mell' test_regex
3:Mark watermellons 12
11:Oliver rockmellons 2
$
В колко линии се съдържа:
$ egrep -c 'mell' test_regex
2
$
Редовете с поне 2 последователни гласни букви:
$ egrep '[aeiou]{2,}' test_regex
Robert pears 4
Lisa peaches 7
Anne mangoes 7
Greg pineapples 3
$
Редовете с цифрата 2, която не е последна в линията:
$ egrep '2.+' test_regex
Fred apples 20
$
С цифра 2 последна в линията :
$ egrep '2$' test_regex
Mark watermellons 12
Susy oranges 12
Oliver rockmellons 2
$
Линиите съдържащи is или go или or :
$ egrep 'or|is|go' test_regex
Susy oranges 5
Terry oranges 9
Lisa peaches 7
Susy oranges 12
Anne mangoes 7
$
Линиите, които започват с буквите от А до К:
$ egrep '^[A-K]' test_regex
Fred apples 20
Anne mangoes 7
Greg pineapples 3
Betty limes 14
$
$cat > test1
ivan.momtchev@tu-sofia.bg
ivan
ivo@tu-sofia.bg
ivo@tu-sofia.bg@tu-sofia.bg
username@hostname.com
$
$ cat test1
ivan.momtchev@tu-sofia.bg
ivan
ivo@tu-sofia.bg
ivo@tu-sofia.bg@tu-sofia.bg
username@hostname.com
$
$
$ egrep
'^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$'
test1
ivan.momtchev@tu-sofia.bg
ivo@tu-sofia.bg
username@hostname.com
$
$man 7 regex
$man egrep