INDEVELOPMENTbeta






Subskrybuj m1chu.eu – another devblog
 
  •  Marek: Problem z filter_var jest taki że ta funkcja sprawdza poprawność mail`a z RFC, ale niech ktoś spróbuje...
  •  m1chu: Nie. Kwestia dwóch, trzech dni – w tym stworzenie wpisu :]
  •  magda: Fantastyczne zdjęcia. Sporo czasu zajęło wyszukanie ich?
  •  :P: Oki znalazłem twojego maila chyba był na stronie utnij.eu więc chyba to ten zabieram się za pisanie maila
  •  googlebot: http://code.google.com/p/isema il/source/browse/trunk/is_emai l.php Grunt to znajomosc RFC 5322 :-)...
  •  m1chu: Jak tylko mam czas, to interesy (byleby nie męskie ;]), zawsze mnie interesują. Trudno jednak żebym to...
  •  :P: M1chu mam dla ciebie pewien interes :) a mianowicie tworze pewną stronę i wiąże z nią duże plany i chodzi o...

Ankieta!

  • Na blogu brakuje mi artykułów o...

    View Results

    Loading ... Loading ...




15 przydatnych wyrażeń regularnych w PHP


Gotowe wyrażenia regularne

W pewnym stadium zaawansowania wyrażenia regularne stają się potężnym narzędziem każdego programisty PHP (i nie tylko). A to dlatego, że pozwalają na wykonywanie operacji, których często nie sposób dokonać w prosty sposób przy pomocy standardowych funkcji zawartych w tym języku. Walidacja zawartości zmiennych, czy podmienianie specyficznej części ich zawartości – na to pozwalają wyrażenia regularne. 15-ście przykładowych, najbardziej niezbędnych dla każdego web developera, skompletowałem w dalszej części artykułu. Do Waszej dyspozycji oddaję także prosty serwis sprawdzający poprawność wprowadzanych wzorców.

1. Walidacja adresu e-mail opartego na hoście

Wzorzec:

/^([a-z0-9]{1})([^\s\t\.@]*)((\.[^\s\t\.@]+)*)@([a-z0-9]{1})((([a-z0-9-]*[-]{2})|([a-z0-9])*|([a-z0-9-]*[-]{1}[a-z0-9]+))*)((\.[a-z0-9](([a-z0-9-]*[-]{2})|([a-z0-9]*)|([a-z0-9-]*[-]{1}[a-z0-9]+))+)*)\.([a-z0-9]{2,6})([.]?)$/Diu

Opis:

Wyrażenie ma za zadanie sprawdzać, czy wprowadzony przez użytkownika adres e-mail ma poprawną formę. Aby test zakończył się sukcesem muszą zostać spełnione następujące warunki:

  • nazwa użytkownika musi zaczynać się od znaku litery lub cyfry, nie może zawierać spacji, tabulatorów, aty, za to mogą się znajdować w nim kropki, pod warunkiem, że nie występują jedna, po drugiej,
  • po nazwie użytkownika musi pojawiać się znak małpy,
  • domena, podobnie jak nazwa użytkownika, musi rozpoczynać się od litery, bądź cyfry, po czym do znaków dozwolonych dochodzą - oraz ., pod warunkiem, że pierwszy z wcześniej wymienionych znaków nie znajduje się na początku lub na końcu nazwy subdomeny (wyjątkiem są dwa myślniki na jej końcu odpowiadające często prefiksom xn--), a drugi nie jest poprzedzany swoim odpowiednikiem. TLD może mieć długość od dwóch do sześciu znaków,
  • domena może być zakończona kropką,
  • rozwiązanie nie sprawdza jak długi jest wprowadzony adres e-mail.

Strona testowa:

Tutaj.

Tekst spełniający warunki:

2.a_a-d@n-do.x-d.pl

Tekst nie spełniający warunków:

2.a_a-d@n-do.x-d.v-.pl (część domeny kończąca się nieprawidłowym znakiem)

Uwagi:

Jeżeli rozwiązanie w jakimkolwiek stopniu zawiedzie można pokusić się o użycie wyrażenia z ostatniej aktualizacji pliku logical_filters.c ze źródeł PHP.

Rozwiązanie oparte o wyrażenie regularne:

$email = trim('adres@domena.pl');
if ( !preg_match('/^([a-z0-9]{1})([^\s\t\.@]*)((\.[^\s\t\.@]+)*)@([a-z0-9]{1})((([a-z0-9-]*[-]{2})|([a-z0-9])*|([a-z0-9-]*[-]{1}[a-z0-9]+))*)((\.[a-z0-9](([a-z0-9-]*[-]{2})|([a-z0-9]*)|([a-z0-9-]*[-]{1}[a-z0-9]+))+)*)\.([a-z0-9]{2,6})([.]?)$/Diu', $email) )
{
	print 'Nieprawidłowy adres e-mail';
}

Rozwiązanie oparte o filter_var (PHP >= 5.2):

$email = trim('adres@domena.pl');
if ( (bool)filter_var($email, FILTER_VALIDATE_EMAIL) === false )
{
	print 'Nieprawidłowy adres e-mail';
}

2. Walidacja adresu e-mail opartego na hoście lub IPv4 serwera

Wzorzec:

/^([a-z0-9]{1})([^\s\t\.@]*)((\.[^\s\t\.@]+)*)@((([a-z0-9]{1})((([a-z0-9-]*[-]{2})|([a-z0-9])*|([a-z0-9-]*[-]{1}[a-z0-9]+))*)((\.[a-z0-9](([a-z0-9-]*[-]{2})|([a-z0-9]*)|([a-z0-9-]*[-]{1}[a-z0-9]+))+)*)\.([a-z0-9]{2,6})([.]?))|((\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))$/Diu

Opis:

Wyrażenie ma za zadanie sprawdzać, czy wprowadzony przez użytkownika adres e-mail ma poprawną formę. Aby test zakończył się sukcesem muszą zostać spełnione warunki z poprzedniego punktu oraz:

  • po znaku @ musi się pojawić opisany już wcześniej prawidłowo sformowany host lub adres IPv4 serwera w postaci czterech, dziesiętnych oktetów.

Strona testowa:

Tutaj.

Tekst spełniający warunki:

2.a_a-d@64.64.100.100

Tekst nie spełniający warunków:

2.a_a-d@64.64.256.100 (trzeci oktet jest po za zakresem)

Uwagi:

Jeżeli rozwiązanie w jakimkolwiek stopniu zawiedzie można pokusić się o użycie wyrażenia z ostatniej aktualizacji pliku logical_filters.c ze źródeł PHP.

Rozwiązanie oparte o wyrażenie regularne:

$email = trim('adres@85.64.100.100');
if ( !preg_match('/^([a-z0-9]{1})([^\s\t\.@]*)((\.[^\s\t\.@]+)*)@((([a-z0-9]{1})((([a-z0-9-]*[-]{2})|([a-z0-9])*|([a-z0-9-]*[-]{1}[a-z0-9]+))*)((\.[a-z0-9](([a-z0-9-]*[-]{2})|([a-z0-9]*)|([a-z0-9-]*[-]{1}[a-z0-9]+))+)*)\.([a-z0-9]{2,6})([.]?))|((\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))$/Diu', $email) )
{
	print 'Nieprawidłowy adres e-mail';
}

Rozwiązanie oparte o filter_var (PHP >= 5.2):

$email = trim('adres@domena.pl');
if ( (bool)filter_var($email, FILTER_VALIDATE_EMAIL) === false )
{
	print 'Nieprawidłowy adres e-mail';
}

3. Prosta weryfikacja adresu URL

Wzorzec:

/^(http|ftp)([s]{0,1}):\/\/([a-z0-9]{1})((([a-z0-9-]*[-]{2})|([a-z0-9])*|([a-z0-9-]*[-]{1}[a-z0-9]+))*)((\.[a-z0-9](([a-z0-9-]*[-]{2})|([a-z0-9]*)|([a-z0-9-]*[-]{1}[a-z0-9]+))+)*)(\.([a-z0-9]{2,6})){0,1}((:[0-9]){0}|(:[1-9]{1}[0-9]*))\//iu

Opis:

Zweryfikować, czy użytkownik wprowadził adres URL, wg wzoru:

protokół://adres_serwera:port/
  • dozwolone protokoły: http, https, ftp, ftps,
  • adres serwera w formie serwera lokalnego, subdomen, domeny i rozszerzenia,
  • port jest opcjonalny,
  • dalsze wprowadzone dane (jak Query String) nie są sprawdzane,
  • konstrukcja jest przeznaczona do sprawdzanie adresów opartych na IPv4.

Strona testowa:

Tutaj.

Tekst spełniający warunki:

http://m1chu.eu/

Tekst nie spełniający warunków:

htt://adres.com/temp/ (nieprawidłowy schemat)

Rozwiązanie oparte o wyrażenie regularne:

$url = trim('http://m1chu.eu');
if ( !preg_match('/^(http|ftp)([s]{0,1}):\/\/([a-z0-9]{1})((([a-z0-9-]*[-]{2})|([a-z0-9])*|([a-z0-9-]*[-]{1}[a-z0-9]+))*)((\.[a-z0-9](([a-z0-9-]*[-]{2})|([a-z0-9]*)|([a-z0-9-]*[-]{1}[a-z0-9]+))+)*)(\.([a-z0-9]{2,6})){0,1}((:[0-9]){0}|(:[1-9]{1}[0-9]*))\//iu', $url) )
{
	print 'Nieprawidłowy adres URL';
}

4. Wycinanie hosta z portem z adresu URL

Wzorzec:

/^(http|ftp)([s]{0,1}):\/\/((.*)\.[a-z0-9]{2,6}|((\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5]))){0,1}((:[0-9]){0}|(:[1-9]{1}[0-9]*))\//iu

Opis:

Pobrać host wraz z portem (jeżeli został podany) z URI. Pozostałe zasady są tożsame z wymienionymi w poprzednim punkcie.

Strona testowa:

Tutaj.

Tekst spełniający warunki:

http://m1chu.eu:80/ (zwróci: m1chu.eu:80)

Tekst nie spełniający warunków:

htt://adres.com/temp/ (nieprawidłowy schemat)

Rozwiązanie oparte o wyrażenie regularne:

$url = trim('ftps://stro.eu:1000/file.exe');
if ( preg_match('/^(http|ftp)([s]{0,1}):\/\/((.*)\.[a-z0-9]{2,6}|((\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5]))){0,1}((:[0-9]){0}|(:[1-9]{1}[0-9]*))\//iu', $url, $matches) )
{
	// $matches[3] - nazwa serwera z domeną lub adres IPv4
	// $matches[10] - port
	print $matches[3] . ':' . $matches[10];
}

5. Sprawdzanie adresu IP (protokół IPv4)

Wzorzec:

/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/Du

Opis:

Wykryć poprawność wprowadzonego w formie dziesiętnych oktetów IP (w wersji czwartej protokołu).

Strona testowa:

Tutaj.

Tekst spełniający warunki:

0.0.0.0

Tekst nie spełniający warunków:

101.256.0.1 (drugi oktet poza zakresem)

Rozwiązanie oparte o wyrażenie regularne:

$ipv4 = trim('192.168.0.1');
if ( !preg_match('/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/Du', $ipv4) )
{
	print 'Nieprawidłowy adres IPv4';
}

Rozwiązanie oparte o filter_var (PHP >= 5.2):

$email = trim('192.168.0.1');
if ( (bool)filter_var($ipv4, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === false )
{
	print 'Nieprawidłowy adres IPv4';
}

6. Sprawdzamy adres IP z wykluczeniem puli prywatnych adresów (protokół IPv4)

Wzorzec:

/^([1-9]{1}[1-9]{0,1}|1\d([1-6]{1}|[8-9]{1})|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-4])$/Du

Opis:

Wykryć poprawność wprowadzonego IP (w wersji czwartej protokołu) z wykluczeniem części prywatnych i zastrzeżonych pul. Metoda nie dotyczy masek podsieci. Objęte wyjątki:

  • 10.0.0.0 – 10.255.255.255,
  • 0.0.0.0 – 0.255.255.255,
  • 255.255.255.255,
  • 127.0.0.0 – 127.255.255.255.

Strona testowa:

Tutaj.

Tekst spełniający warunki:

192.168.0.136

Tekst nie spełniający warunków:

0.0.0.0 (adres prywatny)

Uwagi:

Stosując funkcję ze zbioru filter_* odrzucone zostaną wszystkie zakresy adresów prywatnych i zastrzeżonych (np. 255.255.255.x).

Rozwiązanie oparte o wyrażenie regularne:

$ipv4 = trim('68.78.205.0');
if ( !preg_match('/^([1-9]{1}[1-9]{0,1}|1\d([1-6]{1}|[8-9]{1})|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-4])$/Du', $ipv4) )
{
	print 'Nieprawidłowy adres IPv4';
}

Rozwiązanie oparte o filter_var (PHP >= 5.2):

$email = trim('68.78.205.0');
if ( (bool)filter_var($ipv4, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) === false )
{
	print 'Nieprawidłowy adres IPv4';
}

7. Sprawdzamy adres IP (protokół IPv6 i IPv4)

Wzorzec:

/^((([0-9A-Fa-f]{1,4}:){7}(([0-9A-Fa-f]{1,4})|:))|(([0-9A-Fa-f]{1,4}:){6}(:|((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})|(:[0-9A-Fa-f]{1,4})))|(([0-9A-Fa-f]{1,4}:){5}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:){4}(:[0-9A-Fa-f]{1,4}){0,1}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:){3}(:[0-9A-Fa-f]{1,4}){0,2}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:){2}(:[0-9A-Fa-f]{1,4}){0,3}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:)(:[0-9A-Fa-f]{1,4}){0,4}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(:(:[0-9A-Fa-f]{1,4}){0,5}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})))(%.+)?$/Du

Opis:

Wykryć poprawność wprowadzonego IP (w wersji szóstej i czwartej protokołu).

Strona testowa:

Tutaj.

Tekst spełniający warunki:

fe80:0:0:0:0204:61ff:254.157.241.86

Tekst nie spełniający warunków:

2001:::db8:: (błędna notacja)

Uwagi:

Stosując funkcję ze zbioru filter_* odrzucone zostaną wszelkie adresy IPv4. W przedstawionym wyrażeniu regularnym adresy z tej wersji są akceptowane zarówno występując samotnie, jak i w postaci sekwencji czterech ostatnich bajtów w IPv6 (np. :247.125.68.4).

Rozwiązanie oparte o wyrażenie regularne:

$ipv6 = trim('fe80::204:61ff:fe9d:f156');
if ( !preg_match('/^((([0-9A-Fa-f]{1,4}:){7}(([0-9A-Fa-f]{1,4})|:))|(([0-9A-Fa-f]{1,4}:){6}(:|((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})|(:[0-9A-Fa-f]{1,4})))|(([0-9A-Fa-f]{1,4}:){5}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:){4}(:[0-9A-Fa-f]{1,4}){0,1}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:){3}(:[0-9A-Fa-f]{1,4}){0,2}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:){2}(:[0-9A-Fa-f]{1,4}){0,3}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:)(:[0-9A-Fa-f]{1,4}){0,4}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(:(:[0-9A-Fa-f]{1,4}){0,5}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})))(%.+)?$/Du', $ipv6) )
{
	print 'Nieprawidłowy adres IPv6/IPv4';
}

Rozwiązanie oparte o filter_var (PHP >= 5.2):

$ipv6 = trim('fe80::204:61ff:fe9d:f156');
if ( (bool)filter_var($ipv6, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false )
{
	print 'Nieprawidłowy adres IPv6';
}

8. Wykrywanie kolorów RGB w postaci szesnastkowej

Wzorzec:

/^#?[0-9a-f]{3}(?:[0-9a-f]{3})?$/Diu

Opis:

Sprawdzić, czy wprowadzone dane są szesnastkowymi odpowiednikami zapisu kolorów modelu RGB.

Strona testowa:

Tutaj.

Tekst spełniający warunki:

#ff0000

Tekst nie spełniający warunków:

#a0hfg1 (g i h nie są znakami używanymi przy zapisie heksadecymalnym)

Rozwiązanie oparte o wyrażenie regularne:

$hex = trim('#0F15a2');
if ( !preg_match('/^#?[0-9a-f]{3}(?:[0-9a-f]{3})?$/Diu', $hex) )
{
	print 'Nieprawidłowy kod szesnastkowy koloru!';
}

9. Proste sprawdzenie nazwy użytkownika

Wzorzec:

/^([a-z0-9]{1})([a-z0-9_-]{2,11})$/Diu

Opis:

Wprowadzone dane muszą rozpoczynać się od znaku alfanumerycznego. Kolejne znaki mogą być ponadto myślnikiem lub podkreśleniem. Długość tekstu nie może być większa niż 12ście znaków.

Strona testowa:

Brak.

Tekst spełniający warunki:

m1chu

Tekst nie spełniający warunków:

_nick (pierwszy znak nie jest cyfrą, ani literą)

Rozwiązanie oparte o wyrażenie regularne:

$username = trim('m1chu');
if ( !preg_match('/^([a-z0-9]{1})([a-z0-9_-]{2,11})$/Diu', $username) )
{
	print 'Nieprawidłowa nazwa użytkownika!';
}

10. Proste sprawdzenie hasła użytkownika

Wzorzec:

/^(?=[a-z0-9_#@%\*-]*?[A-Z])(?=[a-z0-9_#@%\*-]*?[a-z])(?=[a-z0-9_#@%\*-]*?[0-9])([a-z0-9_#@%\*-]{8,24})$/Diu

Opis:

Wpisane hasło użytkownika musi mieć od ośmiu, do dwudziestu czterech znaków, pośród których musi być co najmniej jedna wielka litera, jedna mała i jedna cyfra. Dodatkowo dozwolone są: _, #, @, %, * i -.

Strona testowa:

Brak.

Tekst spełniający warunki:

1xY#n6%2V

Tekst nie spełniający warunków:

@1bbd2 (za krótki ciąg, brak wielkiej litery)

Rozwiązanie oparte o wyrażenie regularne:

$password = trim('To#jEst@_haSL-o%usera*');
if ( !preg_match('/^(?=[a-z0-9_#@%\*-]*?[A-Z])(?=[a-z0-9_#@%\*-]*?[a-z])(?=[a-z0-9_#@%\*-]*?[0-9])([a-z0-9_#@%\*-]{8,24})$/Diu', $password) )
{
	print 'Nieprawidłowa nazwa użytkownika!';
}

11. Zaznaczanie frazy w tekście

Wzorzec:

/\b(fraza)\b/iu

Opis:

Zamienianie podanej frazy na inną lub wystylowanie jej formy. Przydatna funkcja w wyszukiwarkach.

Strona testowa:

Brak.

Działanie:

szukana_fraza -> szukana_fraza

Rozwiązanie oparte o wyrażenie regularne:

$text = 'Wyszukane frazy: wyrażenia, regularne, preg_match, preg_replace';
$find = 'regularne';
print preg_replace('/\b(' . $find . ')\b/iu', '<strong>\\1</strong>', $text);

Rozwiązanie oparte o str_ireplace:

$text = 'Wyszukane frazy: wyrażenia, regularne, preg_match, preg_replace';
$find = 'regularne';
print str_ireplace($find, '<strong>' . $find . '</strong>', $text);

12. Zamiana tekstowych emotikon na graficzne

Opis:

Podmiana tekstowych uśmieszków na ich odpowiedniki graficzne. Wersja z użyciem str_ireplace.

Strona testowa:

Brak.

Rozwiązanie oparte o wbudowaną funkcję PHP:

$text_format = array(
	array(';)', ';-)', 'x)', ';]', ';-]'),
	array(':)', ':-)', '=)', ':]', ':-]'),
	array(':(', ':-(', '=(', ':[', ':-['),
	array(';(', ';-(', 'x(', ';[', ';-['),
	array(':P', ':-P', '=P'),
	array(':D', ':-D', '=D'),
	array(':*', ':-*', '=*'),
	array(':O', ':-O', '=O'),
	array(':/', ':-/', '=/')
	);

$image_format = array(
	'wink.png',
	'smile.png',
	'sad.png',
	'cry.png',
	'tongue.png',
	'bigsmile.png',
	'kiss.png',
	'surprise.png',
	'grimace.png'
	);

$text = 'To jest przykładowy tekst ;] Prawda, że fajny? :-D Pogrymasiłbym trochę =/, ale po co? :) Także do zobaczenia :*';

foreach ( $text_format as $key => $val )
{
	$text = str_ireplace($val, '<img src="smiles/' . $image_format[$key] . '" alt="' . $image_format[$key] . '" />', $text);
}

print $text;

13. Zamiana BBCode na HTML

Wzorzec przykładowy:

/\[b\](.*?)\[\/b\]/Dius

Opis:

Podmiana BBCode poprzez kod HTML. Funkcjonalność znana z forów internetowych.

Strona testowa:

Brak.

Działanie:

[i]pochylenie[/i] -> pochylenie

Uwagi:

W komercyjnych projektach należy skorzystać z bardziej zaawansowanych klas do obsługi tego problemu. Pozwoli to uniknąć np. problemu z nieprawidłowym zagnieżdżeniem kilku tagów BBCode w sobie.

Rozwiązanie oparte o wyrażenie regularne:

function bbcode2html($code) {
	$search = array(
        '/\[b\](.*?)\[\/b\]/Dius',
        '/\[i\](.*?)\[\/i\]/Dius',
        '/\[u\](.*?)\[\/u\]/Dius',
        '/\[s\](.*?)\[\/s\]/Dius',
        '/\[img\=(.*?)\](.*?)\[\/img\]/Dius',
        '/\[img\](.*?)\[\/img\]/Dius',
        '/\[url\](.*?)\[\/url\]/Dius',
        '/\[url\=(.*?)\](.*?)\[\/url\]/Dius',
        '/\[color\=(#?([a-f0-9]{6}|[a-f0-9]{3}))\](.*?)\[\/color\]/Dius',
        '/\[size\=([1-9]{1}[0-9]{0,2})(px|pt|em)\](.*?)\[\/size\]/Dius',
    	'/\[font\=([a-z0-9\s"]+)\](.*?)\[\/font\]/Dius',
    );

	$replace = array(
        '<strong>\\1</strong>',
        '<em>\\1</em>',
        '<span style="text-decoration: underline;">\\1</u>',
        '<strike>\\1</strike>',
        '<img src="\\2" alt="\\1" />',
        '<img src="\\1" alt="" />',
        '<a href="\\1">\\1</a>',
        '<a href="\\1">\\2</a>',
        '<span style="color: \\1;">\\2</span>',
        '<span style="font-size: \\1\\2;">\\3</span>',
    	'<span style="font-family: \\1;">\\2</span>'
    );

	return preg_replace($search, $replace, $code);
}

14. Sprawdzenie poprawności wprowadzonego kodu pocztowego

Wzorzec:

/^[0-9]{2}-?[0-9]{3}$/Du

Opis:

Testowanie poprawności wpisanego kodu pocztowego (w formacie używanym w Polsce). Dozwolone są wersje z myślnikiem pomiędzy drugą i trzecią cyfrą, oraz bez niego.

Strona testowa:

Brak.

Tekst spełniający warunki:

62-150

Tekst nie spełniający warunków:

611-10

Rozwiązanie oparte o wyrażenie regularne:

$postcode = '61-610';
if ( !preg_match('/^[0-9]{2}-?[0-9]{3}$/Du', $postcode) )
{
	print 'Nieprawidłowy kod pocztowy';
}

15. Operowanie na znacznikach XML/XHTML

Wzorzec:

/<([a-z]+)([\s]{1}[^=]+[=]{1}[^<]+)*(?:>(.*)<\/\1>|\s+\/>)/u

Opis:

Sprawdzenie znaczników XML/XHTML oraz pobranie treści znajdującej się pomiędzy nimi.

Strona testowa:

Brak.

Rozwiązanie oparte o wyrażenie regularne:

$tag = '<a href="http://m1chu.eu/" title="m1chu.eu - another devblog">m1chu.eu</a> - <strong>another devblog</strong>';
if ( !preg_match_all('/<([a-z]+)([\s]{1}[^=]+[=]{1}[^<]+)*(?:>(.*)<\/\1>|\s+\/>)/u', $tag, $matches, PREG_PATTERN_ORDER) )
{
	print 'Nieprawidłowa konstrukcja znacznika';
}
else {
	print_r($matches); // print_r($matches[3]) - lista treści zawieranych w tagach
}

Słowem zakończenia

Starałem się jak najdokładniej sprawdzić powyższe wzorce. Nie mniej jednak, jak to zwykle bywa, mogą się w nich znaleźć błędy. Jeżeli ktoś takowe znajdzie, ma jakieś pytania, czy lepsze propozycje to proszę o komentarze pod wpisem.

Jak wspomniałem na wstępie, uruchomiłem serwis pozwalający na sprawdzanie wyrażeń regularnych względem podanego tekstu. Jest on aktualnie w fazie testów, więc mogą występować błędy w jego działaniu. Po zakończeniu wprowadzania poprawek baza wpisów zostanie wyczyszczona do zera. Można go testować, a w przyszłości korzystać pod dwoma adresami:

  1. regexp.pl (adres główny)
  2. regexp.m1chu.eu (adres alternatywny)

Pod względem danych sesyjnych obydwa adresy działają niezależnie. Zapraszam do testowania i wyrażania swojego zdania na moim blogu, w komentarzach tego artykułu.


9 komentarzy

  • gravatar
    1. matipl ()

    Nie wiem czemu podałeś przykłady dla preg_match, a nie wyłącznie filter_var.
    Rozumiem, nie każdy musi mieć PHP 5.2, ale przykładów opartych o regexp jest tysiące w Sieci i nie potrzebnie powielasz i uczysz “nowych” staroci ;)

  • gravatar
    2. m1chu ()

    Można powiedzieć, że przykładów dla filter_var też jest już wiele. Po za tym, do filter_var wystarczy zbiór filtrów i flag, żeby bez problemu tę funkcję obsłużyć. A to można znaleźć w manualu (btw tips tego typu będzie na WH). Po za tym, filter_var nie zawsze się sprawdza (w przypadku FILTER_VALIDATE_URL zwraca niekiedy złe wyniki, co z resztą można zauważyć na stronach testowych podanych przeze mnie powyżej).

  • gravatar
    3. cojack ()

    Co do tych wyrażeń, to nie wiem wg której specyfikacji masz te sprawdzanie adresu e-mail, ale na pewno przydało by się też weryfikacja przez MX, oraz w komentarzach do weryfikacji e-mail poprzez filter_var w manualu jeden z użytkowników napisał:

    in fact, this expression (and the original filter-funktion) ignores RFC 5321 (Section 4.5.3.1. Size Limits and Minimums).

    link-manual

    Więc wg mnie to nie jest poprawna walidacja adresu e-mail.

    Pozdrawiam.

  • gravatar
    4. m1chu ()

    Wg jakich zasad cojack masz wylistowane w pierwszym punkcie. Nie starałem się spełnić wszystkich warunków żadnej specyfikacji. Kwestia długości i rozmiarów została także poruszona w ww. liście. Nie są one sprawdzane. Oczywiście nic nie stoi na przeszkodzie, żeby w jakimś hiper-uber-serwisie ktoś sobie zupgradeował ten przykładowy wzorzec, jeżeli widzi taką potrzebę, bo np. dziennie wchodzi mu na niego pół miliona osób via IPv6 ;]

    Co do rekordów MX. Można przecież użyć checkdnsrr(), czy getmxrr() wraz z fsockopen() (itd.) w tym celu. Ale to już nie jest stricte kwestia tylko wyrażeń regularnych, więc jej nie poruszałem.

    Nie mnie jednak, dzięki za komentarz :]

  • gravatar
    5. m1chu.eu: 15 przydatnych wyrażeń regularnych w PHP | m1chu.eu - another | flaker.pl ()

    [...] 00:26 14/10/2009 15 przydatnych wyrażeń regularnych w PHP | m1chu.eu – another devblog m1chu.eu/…5-przydatnych-wyrazen-reg… Pokaż reakcje /* */ inne strony z tej witryny + obserwuj co [...]

  • gravatar
    6. CapaciousCore ()

    Musze przyznac, ze te regulki sa malo dokladne. Na mojej stronie mozna znalesc link do wyrazenia regularnego ktory sprawdza maila zgodnie z ustalonymi normami… a nie na odwal sie. Dodatkowo te rzutowanie na bool’a jest zbedne. Polecam http://code.google.com/p/isemail/source/browse/trunk/is_email.php

  • gravatar
    7. m1chu ()

    Te regułki, czyli które dokładnie? Proszę, wymień je. Chętnie przeczytam także przykłady, dla których nie spełniają one swojego przeznaczenia.

    Nie widzę też, gdzie na Twojej stronie można znaleźć link do tego wyrażenia regularnego sprawdzającego dokładniej (wg norm) adres e-mail. Jedyne co udało mi się wyszukać to przykład który podałeś z filter_var, który zgoła jest tym samym, co ja dałem jako alternatywa do punktu o wzorcu sprawdzającym poprawność adresu e-mail. I jeżeli uważasz, że wyrażenie które podałem jest “na odwal” to, którego punktu z tych które wymieniłem w opisie nie spełnia? (bo kwestię “norm” już wyjaśniłem, wystarczy przeczytać ze zrozumieniem)

    PS: w swoim tipsie podałeś link do artykułu, w którym autor do weryfikacji używa znacznie uboższego wyrażenia, niż ja tutaj. Rozumiem, że pomimo tego, jego wzorzec nie jest “na odwal” (skoro go polecasz)?

  • gravatar
  • gravatar
    9. Marek ()

    Problem z filter_var jest taki że ta funkcja sprawdza poprawność mail`a z RFC, ale niech ktoś spróbuje założyć takiego mail`a ‘marek…___@wp.pl’ na WP, no raczej nie przejdzie choć jest zgodny z RFC i filter_var go puści. Pytanie co chcemy sprawdzać, a najczęściej jest to jednak prawdopodobieństwo istnienie adresu a nie zgodność z RFC. Lepiej jednak sobie stworzyć własne wyrażenie regularne to nie jest żaden wielki problem. Druga sprawa to sprawdzenie czy adres istnieje, ale to nie ma nic wspólnego z walidacją, czyli sprawdzania rekordów MX i DNS`ów.

Dodaj własny komentarz

Możesz użyć następujących tagów XHTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>