LAB 4 :Wyra
ż
enia regularne
Po co s
ą
wyra
ż
enia regularne?
Cz
ę
stym zadaniem, które wykonuje si
ę
podczas pracy z komputerem jest wyszukiwanie danego fragmentu tekstu w jakim
ś
pliku, zmienianie go,
sprawdzanie, czy dany tekst si
ę
w tym pliku znajduje. Generalnie potrzebujemy narz
ę
dzi do znajdywania wzorca o zadanej charakterystyce w jakim
ś
wi
ę
kszym tek
ś
cie. T
ą
charakterystyk
ę
musimy jako
ś
podawa
ć
. W najprostszym przypadku podajemy po prostu tekst, jaki chcemy znale
źć
. Na przykład, aby
znale
źć
wszystkie linie w pliku
tekst.txt
, w których znajduje si
ę
fragment
est
, wystarczy wykona
ć
polecenie
grep est tekst.txt
Wtedy dla pliku
tekst.txt
o zawarto
ś
ci
To jest plik tekstowy.
Testujemy narz
ę
dzie grep.
Trzecia linia.
A to czwarta linia.
To jest pi
ą
ta linia.
w wyniku otrzymamy
To jest plik tekstowy.
Testujemy narz
ę
dzie grep.
To jest pi
ą
ta linia.
Zamiast wyszukiwa
ć
dan
ą
fraz
ę
, mo
ż
emy chcie
ć
znale
źć
bardziej skomplikowane wzorce, jak na przykład wszystkie adresy email, które znajduj
ą
si
ę
w
danym tek
ś
cie, czy te
ż
wszystkie formy słowa pies. W tych celach potrzebne s
ą
bardziej zaawansowane mo
ż
liwo
ś
ci podawania charakterystyki frazy, której
chcemy szuka
ć
. Tak
ą
mo
ż
liwo
ść
daj
ą
wła
ś
nie wyra
ż
enia regularne.
Składnia
Znaki
Najprostsze wyra
ż
enia regularne składaj
ą
si
ę
z ci
ą
gu znaków. Niektóre znaki s
ą
specjalne, wi
ę
c aby rozpozna
ć
który
ś
z nich, trzeba poprzedza
ć
go
backslashem. Nast
ę
puj
ą
ce znaki s
ą
specjalne:
.
^
$
*
?
[
]
\
. Na przykład, aby wyszuka
ć
w tek
ś
cie fraz
ę
\abc[?]
u
ż
ywamy wyra
ż
enia
\\abc\[\?\]
.
Klasy znaków
Przypu
ść
my,
ż
e chcemy znale
źć
wyst
ą
pienie jednego z ła
ń
cuchów
psa
,
psu
i
psy
. Zatem pierwsze dwa znaki s
ą
ustalone i s
ą
to
ps
. Natomiast przy
trzecim znaku mamy pewn
ą
dowolno
ść
. Chcemy, aby trzeci znak mógł by
ć
równy
a
,
u
lub
y
. Do tego słu
żą
klasy znaków. List
ę
znaków, któr
ą
chcemy
rozpozna
ć
, umieszczamy pomi
ę
dzy nawiasami kwadratowymi:
[auy]
. Nasze wyra
ż
enie wygl
ą
da wi
ę
c tak:
ps[auy]
.
bashtest@host:~$ grep ps[auy] <<KONIEC
> psami
> psom
> psu
> ps
> KONIEC
psami
psu
bashtest@host:~$
W klasach mo
ż
emy podawa
ć
przedziały znaków u
ż
ywaj
ą
c my
ś
lnika. Na przykład
[0-9]
rozpoznaje dowoln
ą
cyfr
ę
. Mo
ż
emy podawa
ć
kilka przedziałów:
[a-zA-Z]
rozpozna dowoln
ą
liter
ę
angielsk
ą
.
Je
ś
li umie
ś
cimy znak
^
na pocz
ą
tku opisu klasy, b
ę
dzie to oznacza
ć
rozpoznawanie wszystkich znaków nie znajduj
ą
cych si
ę
na li
ś
cie. Na przykład
[^xX]
oznacza dowolny znak ró
ż
ny od
x
i
X
. Oczywi
ś
cie mo
ż
emy podawa
ć
te
ż
przedziały.
Je
ś
li chcemy umie
ś
ci
ć
na li
ś
cie znak
]
, nale
ż
y go poda
ć
jako pierwszy na li
ś
cie. Aby umie
ś
ci
ć
^
, nale
ż
y go umie
ś
ci
ć
w dowolnym miejscu, byle nie na
pocz
ą
tku. Wreszcie, aby umie
ś
ci
ć
-
, nale
ż
y go umie
ś
ci
ć
na ko
ń
cu listy.
Ponadto mamy mo
ż
liwo
ść
kojarzenia dowolnego znaku oprócz znaku ko
ń
ca linii. Do tego słu
ż
y znak specjalny
.
(kropka).
Powtórzenia
Znak specjalny
*
próbuje dopasowa
ć
poprzedzaj
ą
cy go element zero lub wi
ę
cej razy w szukanym tek
ś
cie. Na przykład
=*
dopasowuje si
ę
do ci
ą
gu znaków
równo
ś
ci (by
ć
mo
ż
e ci
ą
gu pustego).
Inny przykład, wyra
ż
enie
[a-zA-Z][a-zA-Z0-9_]*
reprezentuje identyfikator, tzn. niepusty ła
ń
cuch znaków zaczynaj
ą
cy si
ę
od litery i składaj
ą
cy si
ę
z
liter, cyfr oraz znaków podkre
ś
lenia.
Znak specjalny
+
jest podobny do
*
z tym,
ż
e próbuje on dopasowa
ć
poprzedzaj
ą
cy go element jeden lub wi
ę
cej razy.
Znak specjalny
?
mówi,
ż
e poprzedzaj
ą
cy element mo
ż
e wyst
ą
pi
ć
, b
ą
d
ź
te
ż
nie. Na przykład wyra
ż
enie
-?[0-9]+
oznacza dowolny niepusty ci
ą
g cyfr, by
ć
mo
ż
e poprzedzony znakiem
-
. Czyli takie wyra
ż
enie mo
ż
e słu
ż
y
ć
do rozpoznawania dowolnej liczby całkowitej (je
ż
eli dopu
ś
cimy to,
ż
e zapis dziesi
ę
tny
liczby mo
ż
e mie
ć
wiod
ą
ce zera).
Ponadto ilo
ść
powtórze
ń
mo
ż
na poda
ć
bardziej w uniwersalny sposób:
symbol powtórzenia liczba powtórze
ń
poprzedzaj
ą
cego elementu
{n}
dokładnie
n
{n,}
co najmniej
n
{,m}
co najwy
ż
ej
m
{n,m}
co najmniej
n
i co najwy
ż
ej
m
Pozycjonowanie
Znaczniki pozycjonuj
ą
ce s
ą
takimi symbolami, które nie s
ą
kojarzone z
ż
adnym ci
ą
giem znaków, ale z pozycj
ą
w tek
ś
cie spełniaj
ą
c
ą
pewne ustalone warunki.
Je
ś
li chcemy, aby wzorzec był dopasowywany od pocz
ą
tku linii, wyra
ż
enie zaczynamy znakiem
^
. Je
ś
li chcemy, aby wzorzec był dopasowywany do ko
ń
ca
linii, wyra
ż
enie ko
ń
czymy znakiem
$
. Gdy u
ż
yjemy oba znaki, wzorzec b
ę
dzie dopasowywany do całej linii.
Na przykład,
ż
eby znale
źć
linie, w których znajduje si
ę
dokładnie jedna kropka, mo
ż
emy u
ż
y
ć
wyra
ż
enia
^[^.]*\.[^.]*$
. U
ż
ycie
^
na pocz
ą
tku i
$
na
ko
ń
cu oznacza,
ż
e zawsze b
ę
dzie próba dopasowania całej linii. Nast
ę
pnie
[^.]*
oznacza dowolny ci
ą
g znaków nie zawieraj
ą
cy kropki, a
\.
oznacza
wyst
ą
pienie kropki (trzeba u
ż
y
ć
\
, bo
.
jest znakiem specjalnym).
Aby znale
źć
lini
ę
, która zaczyna si
ę
od dowolnej liczby spacji, liczby, pó
ź
niej kropki, a nast
ę
pnie spacji i du
ż
ej litery, u
ż
ywamy wyra
ż
enia
^ *[0-9][0-
9]*\. *[A-Z]
. Za pomoc
ą
tego wyra
ż
enia zostan
ą
znalezione na przykład
1. Wst
ę
p
2.Wprowadzenie
13. Zako
ń
czenie
a nie zostan
ą
znalezione takie linie
1 Trafienie
3. echo - komenda wbudowana
4 . Punkt czwarty
2006
^ 1. Wst
ę
p
Oprócz znaczników rozpoznaj
ą
cych pocz
ą
tek i koniec linii, mamy te
ż
szereg znaczników rozpoznaj
ą
cych ko
ń
ce słowa:
\<
znacznik mówi
ą
cy,
ż
e w tym miejscu zaczyna si
ę
nowe słowo
\>
znacznik mówi
ą
cy,
ż
e w tym miejscu ko
ń
czy si
ę
słowo
\b
znacznik mówi
ą
cy,
ż
e w tym miejscu jest kraw
ę
d
ź
słowa (nie zaczyna ani nie ko
ń
czy si
ę
ż
adne słowo)
\B
znacznik mówi
ą
cy,
ż
e w tym miejscu nie znajduje si
ę
kraw
ę
d
ź
słowa
Dokładne definicje, co to jest brzeg słowa, s
ą
nieprzyjemnie skomplikowane i je pominiemy. Przyjrzyjmy si
ę
przykładowi. Dla frazy
Jola jest lojalna
nast
ę
puj
ą
ce wyra
ż
enia zostan
ą
dopasowane do wycinka tej frazy:
•
\<jest\>
•
\bjest\b
•
\Best\b
•
\Bes\B
a poni
ż
sze wyra
ż
enia nie zostan
ą
dopasowane:
•
\<est\>
•
\best\b
•
\Bes\b
•
\>jest\<
Alternatywa
Je
ś
li chcemy, aby był rozpoznawany jeden z dwóch mo
ż
liwych napisów, to mo
ż
emy u
ż
y
ć
alternatywy
|
, na przykład
jeden|dwa
rozpozna albo słowo
jeden
albo słowo
dwa
. Operator
|
mo
ż
e mie
ć
jako argumenty te
ż
inne wyra
ż
enia, na przykład
[0-9]*|[a-z]*|[A-Z]*
rozpoznaje albo ci
ą
g cyfr, albo
ci
ą
g małych liter, albo ci
ą
g du
ż
ych liter.
Priorytety i nawiasowanie
Najwi
ę
kszy priorytet maj
ą
operatory powtórzenia. Je
ś
li chcemy mie
ć
wyra
ż
enie oznaczaj
ą
ce powtórzenie wi
ę
kszej liczby elementów, to mo
ż
emy zrobi
ć
to
poprzez stosowanie nawiasów
( ... )
. Na przykład wyra
ż
enie
([a-z][a-z])*
oznacza ci
ą
g składaj
ą
cy si
ę
z parzystej liczby małych literek.
Najmniejszy priorytet ma alternatywa. Je
ś
li chcemy wpisa
ć
wyra
ż
enie, które rozpoznaje wszystkie słowa, które rozpoczynaj
ą
si
ę
od
Ta
lub od
Do
, to nie
mo
ż
emy napisa
ć
Ta|Do[a-z]*
, gdy
ż
takie wyra
ż
enie rozpoznaje albo słowo
Ta
, albo ci
ą
g literek zaczynaj
ą
cy si
ę
od
Do
. Z pomoc
ą
przychodz
ą
nawiasy:
(Ta|Do)[a-z]*
.
Wyra
ż
enia podstawowe i rozszerzone
Wyra
ż
enia regularne dzielimy na podstawowe i rozszerzone. W wyra
ż
eniach podstawowych znaki
?
,
+
,
{
,
|
,
(
,
)
nie maj
ą
specjalnego znaczenia, zamiast
nich trzeba u
ż
ywa
ć
wersji z backslashem:
\?
,
\+
,
\{
,
\|
,
\(
,
\)
. W wyra
ż
eniach rozszerzonych mo
ż
emy stosowa
ć
wszystkie wymienione znaki specjalne.
Rozró
ż
nienie takie powstało na skutek ró
ż
nych narz
ę
dzi i zachowania kompatybilno
ś
ci mi
ę
dzy nimi. Niektóre narz
ę
dzia u
ż
ywaj
ą
składni z podstawowymi, a
niektóre z rozszerzonymi wersjami wyra
ż
e
ń
regularnych. Przy omawianiu poszczególnych komend powiemy, które u
ż
ywaj
ą
jakiej składni.
Przykłady wykorzystania
grep
Polecenie
grep
jest podstawowym narz
ę
dziem do wyszukiwania wzorca w tek
ś
cie z u
ż
yciem wyra
ż
e
ń
regularnych.
grep
u
ż
ywa podstawowych wyra
ż
e
ń
.
Je
ś
li jest potrzeba u
ż
ycia rozszerzonych wyra
ż
e
ń
mo
ż
na u
ż
y
ć
wtedy w zast
ę
pstwie polecenia
egrep
.
Podstawowe u
ż
ycie, to
grep wzorzec
gdzie wzorzec jest wyra
ż
eniem regularnym. Wzorzec jest wyszukiwany w standardowym wej
ś
ciu i na standardowe wyj
ś
cie s
ą
wypisywane linie zawieraj
ą
ce
wzorzec.
Mo
ż
na poda
ć
plik lub pliki jako argumenty:
grep wzorzec plik
lub
grep wzorzec plik1 plik2 ...
W przypadku jednego pliku, działanie jest takie samo jak bez argumentów, z t
ą
ró
ż
nic
ą
,
ż
e dane s
ą
czytane z pliku, a nie ze standardowego wej
ś
cia.
W wersji z wieloma plikami wzorzec wyszukiwany jest w ka
ż
dym pliku. Wy
ś
wietlane s
ą
linie zawieraj
ą
ce wyst
ą
pienie wzorca poprzedzone nazw
ą
pliku, w
którym został on znaleziony.
Ponadto jest wiele opcji kontroluj
ą
cych sposób szukania i wy
ś
wietlane informacje. Omówimy najprzydatniejsze z nich.
-e wzorzec
alternatywny sposób podania wzorca; przydatny, gdy wyra
ż
enie regularne mo
ż
e zaczyna
ć
si
ę
od znaku
-
-i
ignoruje rozró
ż
nianie wielkich liter,
-c
zlicza tylko liczb
ę
wyst
ą
pie
ń
wzorca,
-w
dopasowuje wzorzec tylko do całych słów,
-x
dopasowuje wzorzec tylko do całych linii,
-v
odwraca sens dopasowania i wyszukuje tylko linie w których nie udało si
ę
dopasowa
ć
wzorca,
-q
nic nie wypisuje na standardowe wyj
ś
cie i ko
ń
czy działania na pierwszym dopasowaniu; przydatne, gdy polecenie
grep
chcemy u
ż
y
ć
jako
warunku.
grep
zwraca zero jako kod wyj
ś
cia, gdy wzorzec uda si
ę
znale
źć
i warto
ść
niezerow
ą
w przeciwnym przypadku. Mo
ż
na to wykorzysta
ć
w poł
ą
czeniu z opcj
ą
-q
w instrukcjach warunkowych. Na przykład
if grep -qw TODO opis_prac.txt; then
echo "Zostało jeszcze co
ś
do zrobienia"
fi
Je
ś
li chcemy z pliku usun
ąć
linie, które pasuj
ą
do wzorca mo
ż
emy zrobi
ć
to w nast
ę
puj
ą
cy sposób:
TMPFILE=/tmp/xyzabcd
cp plik $TMPFILE
grep -xv wzorzec $TMPFILE >plik
rm -f $TMPFILE
expr
Polecenie
expr
oprócz obliczania wyra
ż
e
ń
arytmetycznych ma te
ż
podstawowe operacje na ła
ń
cuchach znakowych. Szczególnie przydatny jest operator
:
.
Jego składnia to
expr ła
ń
cuch : wzorzec
Wzorzec jest wyszukiwany na pocz
ą
tku ła
ń
cucha (czyli tak jakby zawsze na pocz
ą
tku wzorca stał
^
). Je
ś
li zostanie on znaleziony, wypisywana jest liczba
dopasowanych znaków. W przeciwnym razie liczba dopasowanych znaków wynosi 0.
Je
ż
eli we wzorcu były u
ż
ywane nawiasy
\(
i
\)
, zwracany jest ła
ń
cuch dopasowany w tym podwyra
ż
eniu.
Status wyj
ś
cia jest równy zero tylko wtedy, gdy do wzorca uda si
ę
dopasowa
ć
niepusty ci
ą
g znaków.
Oto kilka przykładów:
•
Wy
ś
wietlenie rozszerzenia pliku znajduj
ą
cego si
ę
na zmiennej plik:
expr "$plik" : ".*\.\([^.]*\)"
•
Zmiana rozszerzenia z
tar.gz
na
tgz
pliku na zmiennej plik:
if expr "$plik" : ".*\.tar\.gz$"; then
mv $plik `expr "$plik" : "\(.*\.\)tar\.gz"`tgz
fi
oczywi
ś
cie
if
jest zb
ę
dny je
ś
li wiemy,
ż
e nazwa pliku na pewno ko
ń
czy si
ę
na
.tar.gz
.
sed
Najpro
ś
ciej rzecz ujmuj
ą
c
sed
jest edytorem strumieniowym. Czyta ze standardowego wej
ś
cia lub z pliku, je
ś
li został podany jako argument, nast
ę
pnie
wykonuje operacje podane w komendach edycyjnych i wynik wyrzuca zawsze na standardowe wyj
ś
cie.
Najcz
ęś
ciej
sed
jest u
ż
ywany z komend
ą
edycyjn
ą
postaci
s/wzorzec/zamiennik/
, gdzie
wzorzec
jest podstawowym wyra
ż
eniem regularnym, a
zamiennik
jest ła
ń
cuchem znakowym jakim b
ę
dzie zast
ą
piony znaleziony wzorzec. W ła
ń
cuchu
zamiennik
mo
ż
emy u
ż
ywa
ć
specjalnych sekwencji
odnosz
ą
cych si
ę
do znalezionego tekstu.
\
n, gdzie n jest liczb
ą
, oznacza ła
ń
cuch skojarzony z n-t
ą
par
ą
nawiasów
\( ... \)
. Znak
&
kojarzy z całym
znalezionym ła
ń
cuchem.
Na przykład, aby zamieni
ć
ka
ż
dy ci
ą
g wykrzykników w jeden wykrzyknik mo
ż
na u
ż
y
ć
komendy
s/!\+/!/
:
bashtest@host:~$ echo 'Hej!! Hej!!!! Tutaj!' | sed 's/!\+/!/'
Hej! Hej!!!! Tutaj!
bashtest@host:~$
Domy
ś
lnie
sed
wykonuje zast
ą
pienie tylko przy pierwszym skojarzeniu wzorca w danej linii. Aby szukał wszystkich skojarze
ń
nale
ż
y doda
ć
przyrostek
g
do
komendy edycyjnej:
bashtest@host:~$ echo 'Hej!! Hej!!!! Tutaj!' | sed 's/!\+/!/g'
Hej! Hej! Tutaj!
bashtest@host:~$
Aby zamieni
ć
znak
.
na znak
,
we wszystkich liczbach zmiennopozycyjnych mo
ż
emy u
ż
y
ć
komendy
s/\([0-9]\+\)\.\([0-9]\+\)/\1,\2/g
U
ż
yli
ś
my tutaj odno
ś
ników.
\1
oznacza grup
ę
cyfr przed
.
w znalezionym ła
ń
cuchu, a
\2
oznacza grup
ę
cyfr po
.
.
Do rozdzielania komendy
s
nie trzeba wcale u
ż
ywa
ć
znaku
/
, ale mo
ż
e to by
ć
dowolny wybrany znak. Na przykład komenda
s+C:\\+/mnt/win/+g
zamieni wszystkie wyst
ą
pienia
C:\
na
/mnt/win/
.
sed
mo
ż
e te
ż
słu
ż
y
ć
do filtrowania wej
ś
cia. Opcja
-n
powoduje,
ż
e domy
ś
lnie nic nie jest wypisywane. Trzeba doda
ć
przyrostek
p
do komendy, aby wynik
został wypisany. Na przykład
sed -n 's/[a-zA-Z0-9]/&/p' opis.txt
wypisze tylko te linie pliku
opis.txt
, które zawieraj
ą
znak alfanumeryczny.
Ponadto
sed
posiada znacznie wi
ę
cej ró
ż
nych u
ż
ytkowych funkcji. Mo
ż
na poprzedzi
ć
komend
ę
adresem. Na przykład
sed '20s/.../.../'
zadziała
tylko w 20 linii. Adresem mo
ż
e by
ć
numer linii, wyra
ż
enie regularne albo zakres. S
ą
te
ż
inne komendy, na przykład
sed '/^#/d'
usunie wszystkie linie,
które zaczynaj
ą
si
ę
od znaku
#
.
Przykłady
1.
Podaj wyra
ż
enie regularne rozpoznaj
ą
ce adres strony http.
2.
Podaj wyra
ż
enie regularne rozpoznaj
ą
ce adres mail
3.
Podaj wyra
ż
enie regularne rozpoznaj
ą
ce kod pocztowy
4.
Podaj wyra
ż
enie regularne rozpoznaj
ą
ce numerowane linie na pocz
ą
tku wiersza.
5.
Podaj wyra
ż
enie regularne rozpoznaj
ą
ce komentarz w j
ę
zyku C:
/* ... */
.
/\*([^*]|(\*+[^*/]))*\*+/
6.
Podaj wyra
ż
enie regularne rozpoznaj
ą
ce słowa, w których wyst
ę
puje parzysta liczba wyst
ą
pie
ń
litery
a
.
[b-z]*(a[b-z]*a[b-z]*)*
7.
*
Podaj wyra
ż
enie regularne, które rozpoznaje ci
ą
g znaków składaj
ą
cy si
ę
z parzystej liczby wyst
ą
pie
ń
znaku
a
i znaku
b
.
(aa|bb|(ab|ba)(aa|bb)*(ab|ba))*
Wi
ę
cej wiadomo
ś
ci na:
1.
http://wyrazenia-regularne.pl/
2.
http://www.regular-expressions.info/quickstart.html
3.
http://pl.wikipedia.org/wiki/Wyra%C5%BCenia_regularne
4.
http://www.digipedia.pl/man/grep.1.html
5.
http://www.uky.edu/AS/Classics/regex.html
Opracowano na podstawie: http://wazniak.mimuw.edu.pl/index.php?title=%C5%9Arodowisko_programisty/Wyra%C5%BCenia_regularne