[ Pobierz całość w formacie PDF ]

case_insensitive = /mangy/i
case_insensitive =~ "I'm mangy!" # => 4
case_insensitive =~ "Mangy Jones, at your service." # => 0
multiline = /a.b/m
multiline =~ "banana\nbanana" # => 5
/a.b/ =~ "banana\nbanana" # => nil
# Ale zwróc uwag na to:
/a\nb/ =~ "banana\nbanana" # => 5
extended = %r{ \ was # Dopasowano " was"
\s # Dopasowano jeden bia y znak
a # Dopasowano "a" }xi
extended =~ "What was Alfred doing here?" # => 4
extended =~ "My, that was a yummy mango." # => 8
extended =~ "It was\n\n\na fool's errand" # => nil
Patrz tak e
" Ksi ka Jeffreya Friedla Mastering Regular Expressions4 dostarcza eleganckiego i zwi zle-
go wprowadzenia w tematyk wyra e regularnych, ilustrowanego wieloma praktyczny-
mi przykladami.
" Witryna RegExLib.com (http://regexlib.com/default.aspx) jest obszern baz wyra e regu-
larnych, wyposa on w wyszukiwark .
" Przewodnik po wyra eniach regularnych i ich wykorzystywaniu w j zyku Ruby dost p-
ny jest pod adresem http://www.regular-expressions.info/ruby.html.
" Informacje na temat klasy Regexp mo esz uzyska za pomoc polecenia ri Regexp.
" Receptura 1.19,  Weryfikacja poprawno ci adresów e-mailowych .
4
Wydanie polskie: Wyra enia regularne, wyd. Helion 2001 (http://helion.pl/ksiazki/wyrare.htm)  przyp. t um.
1.17. Dopasowywanie a cuchów za pomoc wyra e regularnych | 59
1.18. Zast powanie wielu wzorców
w pojedynczym przebiegu
Problem
Chcemy wykona kilka operacji typu  znajd i zamie  , sterowanych oddzielnymi wyra e-
niami regularnymi  równolegle, w pojedynczym przej ciu przez la cuch.
Rozwi zanie
Musimy u y metody Regexp.union do zagregowania poszczególnych wyra e regularnych
w pojedyncze wyra enie, pasuj ce do ka dego z wyra e cz stkowych. Zagregowane wyra-
enie musimy nast pnie przekaza jako parametr metody String#gsub wraz z blokiem kodo-
wym bazuj cym na obiekcie MatchData. Wiedz c, do którego z wyra e cz stkowych przy-
porz dkowa mo na znalezion fraz , mo emy wybra odpowiedni fraz zast puj c :
class String
def mgsub(key_value_pairs=[].freeze)
regexp_fragments = key_value_pairs.collect { |k,v| k }
gsub(Regexp.union(*regexp_fragments)) do |match|
key_value_pairs.detect{|k,v| k =~ match}[1]
end
end
end
Oto prosty przyklad u ycia metody mgsub:
"GO HOME!".mgsub([[/.*GO/i, 'Home'], [/home/i, 'is where the heart is']])
# => "Home is where the heart is!"
W powy szym przykladzie damy zamiany dowolnego ci gu ko cz cego si na GO (bez
wzgl du na wielko liter) na ci g Home, za ci gu Home (bez wzgl du na wielko liter) na
ci g is where the heart is.
W poni szym przykladzie zamieniamy wszystkie litery na znak #, a ka dy znak # na liter P:
"To jest liczba #123".mgsub([[/[a-z]/i, '#'], [/#/, 'P']])
# => "#### ## ###### P123"
Dyskusja
Wydawaloby si , e naiwne podej cie polegaj ce na sukcesywnym wywolaniu metody gsub
dla ka dej operacji  znajd i zamie  da identyczny efekt i tylko efektywno ci ust powa
b dzie rozwi zaniu wy ej opisanemu. Jest jednak inaczej, o czym mo emy si przekona , spo-
gl daj c na poni sze przyklady:
"GO HOME!".gsub(/.*GO/i, 'Home').gsub(/home/i, 'is where the heart is')
# => "is where the heart is is where the heart is!"
"To jest liczba #123".gsub(/[a-z]/i, '#').gsub(/#/, 'P')
# => "PP PPPP PPPPPP P123"
Przyczyna rozbie no ci z rozwi zaniem  równoleglym nie jest adn tajemnic : otó w oby-
dwu przypadkach materialem wej ciowym dla drugiego wywolania metody gsub jest wynik
60 | Rozdzia 1. a cuchy
jej pierwszego wywo ania. W wariancie równoleglym natomiast obydwa wywolania metody
gsub operuj na a cuchu oryginalnym. W pierwszym przypadku mo na zniwelowa ow in-
terferencj , zamieniaj c kolejno operacji, w drugim jednak nawet i to nie pomo e.
Do metody mgsub mo na przekaza tak e hasz, w którym poszukiwane frazy s kluczami,
a frazy zast puj ce  warto ciami. Nie jest to jednak rozwi zanie bezpieczne, bowiem ele-
menty hasza s z natury nieuporz dkowane i w zwi zku z tym kolejno zast powania fraz
wymyka si spod kontroli. Znacznie lepszym wyj ciem byloby u ycie tablicy elementów ty-
pu  klucz-warto  . Poni szy przyklad z pewno ci ulatwi zrozumienie tego problemu:
"between".mgsub(/ee/ => 'AA', /e/ => 'E') # Z y kod
# => "bEtwEEn"
"between".mgsub([[/ee/, 'AA'], [/e/, 'E']]) # Dobry kod
# => "bEtwAAn"
W drugim przypadku najpierw wykonywane jest pierwsze zast powanie. W pierwszym przy-
padku jest ono wykonywane jako drugie i szukana fraza nie zostaje znaleziona  to jedna
z osobliwo ci implementacji haszów w j zyku Ruby.
Je li efektywno programu jest czynnikiem krytycznym, nale y zastanowi si nad inn im-
plementacj metody mgsub. Im wi cej bowiem fraz do znalezienia i zast pienia, tym dlu ej
trwa b dzie cala operacja, poniewa metoda detect wykonuje sprawdzenie dla ka dego wy-
ra enia regularnego i dla ka dej znalezionej frazy.
Patrz tak e
" Receptura 1.17,  Dopasowywanie la cuchów za pomoc wyra e regularnych .
" Czytelnikom, którym zagadkowa wydaje si skladnia Regexp.union(*regexp_fragments),
polecamy przestudiowanie receptury 8.11,  Metody wywolywane ze zmienn liczb ar-
gumentów .
1.19. Weryfikacja poprawno ci adresów e-mailowych
Problem
Chcemy sprawdzi , czy podany adres e-mailowy jest poprawny.
Rozwi zanie
Oto kilka przykladowych adresów e-mail  poprawnych
test_addresses = [ # Poni sze adresy czyni zado specyfikacji RFC822.
'joe@example.com', 'joe.bloggs@mail.example.com',
'joe+ruby-mail@example.com', 'joe(and-mary)@example.museum',
'joe@localhost',
i niepoprawnych
# Poni sze adresy s niezgodne ze specyfikacj RFC822
'joe', 'joe@', '@example.com',
'joe@example@example.com',
'joe and mary@example.com' ]
1.19. Weryfikacja poprawno ci adresów e-mailowych | 61
Oto kilka przykladowych wyra e regularnych filtruj cych bl dne adresy e-mailowe. Pierw-
sze z nich ogranicza si do bardzo elementarnej kontroli.
valid = '[^ @]+' # Wyeliminowanie znaków bezwzgl dnie niedopuszczalnych w adresie e-mail
username_and_machine = /^#{valid}@#{valid}$/
test_addresses.collect { |i| i =~ username_and_machine }
# => [0, 0, 0, 0, 0, nil, nil, nil, nil, nil]
Drugie z wyra e eliminuje adresy typowe dla sieci lokalnej, w rodzaju joe@localhost 
wi kszo aplikacji nie zezwala na ich u ywanie.
username_and_machine_with_tld = /^#{valid}@#{valid}\.#{valid}$/
test_addresses.collect { |i| i =~ username_and_machine_with_tld }
# => [0, 0, 0, 0, nil, nil, nil, nil, nil, nil]
Niestety, jak za chwil zobaczymy, prawdopodobnie poszukujemy rozwi zania nie tego pro-
blemu.
Dyskusja
Wi kszo systemów weryfikacji adresów e-mailowych opiera swe funkcjonowanie na naiw-
nych wyra eniach regularnych, podobnych do prezentowanych powy ej. Niestety, wyra e-
nia takie bywaj cz sto zbyt rygorystyczne, wskutek czego zdarza si , e poprawny adres zo-
staje odrzucony. Jest to powszechna przyczyna frustracji u ytkowników posluguj cych si
nietypowymi adresami w rodzaju joe(and-mary)@example.museum oraz u ytkowników wyko-
rzystuj cych w swych adresach specyficzne cechy systemu e-mail (joe+ruby-mail@example.com).
Prezentowane powy ej wyra enia regularne cierpi na dokladnie odwrotn przypadlo 
nie kwestionuj c nigdy adresów poprawnych, akceptuj niektóre niepoprawne.
Dlaczego wi c nie stworzy (publicznie znanego) wyra enia regularnego, które z zadaniem
weryfikacji adresów e-mailowych poradzi sobie zawsze? Otó dlatego, e by mo e wyra e-
nie takie wcale nie istnieje  definicji skladni adresu e-mailowego zarzuci mo na wszystko,
tylko nie prostot . Haker j zyka Perl, Paul Warren, w stworzonym przez siebie module Mail
::RFC822:Address zdefiniowal wyra enie regularne skladaj ce si z 6343 znaków, lecz na-
wet ono wymaga przetwarzania wst pnego dla absolutnie (w zamierzeniu) bezbl dnej wery-
fikacji adresu. Wyra enia tego mo na u y bez zmian w j zyku Ruby  zainteresowani Czy-
telnicy mog znale je w katalogu Mail-RFC822-Address-0.3 na CD-ROM-ie dol czonym
do niniejszej ksi ki. [ Pobierz całość w formacie PDF ]

  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • glaz.keep.pl