PCRE wyrażenia regularne

Z DooBLER wiki

Spis treści


Wstęp

Ta strona przedstawia podstawy tworzenia i używania wyrażeń regularnych Perla.


W PHP następujące funkcje używają wyrażen PCRE:

  • preg_filter — Perform a regular expression search and replace
  • preg_grep — Zwraca elementy tablicy pasujące do wyrażenia
  • preg_last_error — Zwraca kod błędu dla ostatnio użytego wyrażenia PCRE
  • preg_match_all — Perform a global regular expression match
  • preg_match — Perform a regular expression match
  • preg_quote — Quote regular expression characters
  • preg_replace_callback — Perform a regular expression search and replace using a callback
  • preg_replace — Perform a regular expression search and replace
  • preg_split — Split string by a regular expression

Poradnik

Proste dopasowanie słów

Najprostszym wyrażeniem regularnym jest po prosty słowo, lub bardziej dokłanie zbiór znaków. Wyrażenie regularne zostanie dopasowane poprawnie do każdego tekstu zawierającego to słowo:

  1. "Hello World" =~ /World/;  # matches



Wyrażenia takie jak to są przydatne przy tworzeniu warunków:

  1. print "It matches\n" if "Hello World" =~ /World/;


Wynik wyrażenia może zostać odwrócony przez operator !~:

  1. print "It doesn't match\n" if "Hello World" !~ /World/;


Tekst w wyrażeniu regularnym może zostać zamieniony na zmienną:

  1. $greeting = "World";
  2. print "It matches\n" if "Hello World" =~ /$greeting/;


Jeśli porównujesz do $_ , część $_ =~ może zostać pominięta:

  1. $_ = "Hello World";
  2. print "It matches\n" if /World/;


Dodatkowo, domyślne ograniczniki dopasowania // mogą zostać zmienione na dowolne inne przez dodanie m na początku:

  1. "Hello World" =~ m!World!;   # pasuje, ograniczane przez '!'
  2. "Hello World" =~ m{World};   # pasuje, ograniczane przez '{}'
  3. "/usr/bin/perl" =~ m"/perl"; # pasuje po '/usr/bin',
  4.                              # '/' staje się zwykłym znakiem


Wyrażenie regularne musi pasować do tekstu dokładnie w takiej postaci jak zostało zapisane:

  1. "Hello World" =~ /world/;  # nie pasuje, ze względu na wielkość znaków
  2. "Hello World" =~ /o W/;    # pasuje, spacja ' ' jest zwykłym znakiem
  3. "Hello World" =~ /World /; # nie pasuje, brak spacji ' ' na końcu tekstu


Wyrażenie zawsze jest dopasowywane do najwcześniejszego wystąpienia w przetwarzanym tekście:

  1. "Hello World" =~ /o/;       # dopasowane zostało 'o' w 'Hello'
  2. "That hat is red" =~ /hat/; # dopasowane zostało 'hat' w 'That'


Nie wszystkie znaki mogą zostać użyte "jak są" w wyrażeniu regularnym. Niektóre znaki nazywane metaznakami są zarezerwowane jako znaki spełniające określone funkcje w wyrażeniu. Te znaki to:

{}[]()^$.|*+?\


Metaznaki mogą zostać dopasowane jak zwykłe znaki przez dodanie przed nimi backslash'a \:

  1. "2+2=4" =~ /2+2/;    # nie pasuje, +  jest metaznakiem
  2. "2+2=4" =~ /2\+2/;   # pasuje, \+ jest traktowane jak zwykłu symbol +
  3. 'C:\WIN32' =~ /C:\\WIN/;               # pasuje
  4. "/usr/bin/perl" =~ /\/usr\/bin\/perl/; # pasuje

W ostatnim wyrażeniu backslasch został również dodany do zwykłego slash'a / ponieważ jest on w tym przypadku ogranicznikiem dopasowania.


Nie wyświetlane znaki ASCII powinny być reprezentowane przez sekwencje specjalne. Dobre przykłady takich znaków to \t dla TAB, \n dla znaku nowej linii, \r dla tzw. powrotu karetki. Inne znaki mogą być reprezentowane przez sekwencje specjalne ósemkowe \033 lub szesnastkowe \x1B:

  1. "1000\t2000" =~ m(0\t2)        # pasuje
  2. "cat"        =~ /\143\x61\x74/ # pasuje, ale jest to dziwny sposób by napisać cat


Wyrażenia regularne są traktowane zazwyczaj jak cudzysłowy " więc działa bezpośrednie wstawianie zmiennych:

  1. $foo = 'house';
  2. 'cathouse' =~ /cat$foo/;   # pasuje
  3. 'housecat' =~ /${foo}cat/; # pasuje


We wszystkich powyższych przykładach jeśli wyrażenie pasuje gdziekolwiek w tekście jest to rozpoznawane jako dopasowanie poprawne. Aby sprecyzować, w którym miejscu wyrażenie powinno pasować można użyć metaznaków kotwicznych (anchor) ^ i $. Znak ^ dopasowuje na początku tekstu, a znak $ na końcu lub przed znakiem nowej linii na końcu tekstu. Kilka przykładów:

  1. $foo = 'house';
  2. "housekeeper" =~ /keeper/;         # pasuje
  3. "housekeeper" =~ /^keeper/;        # nie pasuje
  4. "housekeeper" =~ /keeper$/;        # pasuje
  5. "housekeeper\n" =~ /keeper$/;      # pasuje
  6. "housekeeper" =~ /^housekeeper$/;  # pasuje


Używanie klas znakowych

Użycie klas znakowych umożliwia ustawienie grupy możliwych znaków do dopasowania zamiast jednego konretnego znaku w określonym miejscu wyrażenia regularnego. Klasy znaków są wyznaczane przez nawiasy kwadratowe [...] z grupą znaków między nimi. Kilka przykładów:

  1. /cat/;            # pasuje 'cat'
  2. /[bcr]at/;        # pasuje 'bat', 'cat', lub 'rat'
  3. "abc" =~ /[cab]/; # pasuje 'a'

W ostatnim przykładzie - nawet jeśli c jest pierwszą literą w klasie znaków, to najwcześniejszym miejscem do którego pasuje wyrażenie regularne jest a w tekście.

  1. /[yY][eE][sS]/; # pasuje 'yes' bez uwzględniania wielkości liter
  2.                 # 'yEs', 'Yes', 'YES', itp.
  3. /yes/i;         # także dopasuje 'yes' bez uwzględniania wielkości liter

Ostatni przykład pokazuje użycie operatora i, który sprawia, że wielkość liter nie ma znaczenia przy dopasowaniu.


Klasy znaków również posiadają zbiór znaków o specjalnym znaczeniu (metaznaki). Jednak metaznaki wewnąrz klasy znaków są inne niż na zewnątrz. Te znaki specjalne to -]\^$ jeśli mają zostać dopasowane należy dodać przed nimi backslash \ jak przy zwykłych metaznakach:

  1. /[\]c]def/; # pasuje ']def' lub 'cdef'
  2. $x = 'bcr';
  3. /[$x]at/;   # pasuje 'bat, 'cat', lub 'rat'
  4. /[\$x]at/;  # pasuje '$at' lub 'xat'
  5. /[\\$x]at/; # pasuje '\at', 'bat, 'cat', lub 'rat'


Metaznak - jest operatorem zakresu dzięki temo możemy skrócić zapis w postaci [0123456789] lub [abc...xyz] na ospowiednio [0-9] i [a-z]

  1. /item[0-9]/;  # pasuje 'item0' lub 'item1' lub ... lub 'item9'
  2. /[0-9a-fA-F]/;  # pasują cyfry w systemie szesnastkowym

Jeśli - jest pierwszym lub ostatnim znakiem w klasie znaków jest on traktowany jak zwykły znak minus/pauza.


Jeśli znak specjalny ^ znajduje się na pierwszej pozycji w klasie znaków wtedy tworzy on zaprzeczenie tej klasy, która zostanie dopasaowana do wszystkich znaków poza tymi, które się w niej znajdują. Oba warianty [...] lub [^...] muszą zostać spełnione w wyrażeniu regularnym aby zostało ono dopasowane.

  1. /[^a]at/;  # nie pasuje 'aat' lub 'at', ale pasują
  2.            # wszystkie pozostałe 'bat', 'cat, '0at', '%at', itp.
  3. /[^0-9]/;  # pasują wszystkie znaki nie będące cyframi
  4. /[a^]at/;  # pasuje 'aat' lub '^at'; tutaj '^' jest traktowane jak
  5.            # zwykły znak bo nie jest na początku klasy znaków


Perl posiada kilka skrótów dla często używanych klas znaków.

  • \d reprezentuje cyfry, odpowiada mu:
    [0-9]
  • \s reprezentuje tzw. białe znaki, odpowiada mu:
    [\ \t\r\n\f]
  • \w reprezentuje znaki alfanumeryczne i znak _, odpowiada mu:
    [0-9a-zA-Z_]
  • \D jest zaprzeczeniem \d,reprezentuje wszystkie znaki poza cyframi , odpowiada mu:
    [^0-9]
  • \S jest zaprzeczeniem \s, odpowiada mu:
    [^\s]
  • \W jest zaprzeczeniem \w, odpowiada mu:
    [^\w]
  • Dodatkowo kropka . pasuje do dowolnego znaku poza \n


Wszystkie skróty \d\s\w\D\S\W mogą być używane zarówno wewnątrz jak i na zewnątrz klas znaków. Poniżej kilka przykładów.

  1. /\d\d:\d\d:\d\d/; # pasuje do hh:mm:ss format czasu
  2. /[\d\s]/;         # pasuje do dowolnej cyfry lub białego znaku
  3. /\w\W\w/;         # pasuje do znaku alfanumerycznego, po którym jest
  4.                   # znak nie alfanumeryczny, po którym jest znak alfanumeryczny
  5. /..rt/;           # pasują dowolne dwa znaki, po których jest 'rt'
  6. /end\./;          # pasuje 'end.'
  7. /end[.]/;         # tak samo, pasuje 'end.'


Znak kotwiczny \b pasuje do granicy pomiędzy znakami alfanumerycznym i nie alfanumerycznym \w\W lub \W\w:

  1. $x = "Housecat catenates house and cat";
  2. $x =~ /\bcat/;   # pasuje cat w słowie 'catenates'
  3. $x =~ /cat\b/;   # pasuje cat w słowie 'housecat'
  4. $x =~ /\bcat\b/; # pasuje 'cat' na końcu tekstu

W ostatnim przykładzie koniec tekstu jest rozpoznany jako granica znaków.


Dopasowanie tego lub tamtego

Przy pomocy metaznaku alternatywy | możliwe jest dopasowywanie na raz kilku róznych grup znaków do tekstu. Żeby dopasować dog lub cat utworzymy wyrażenie regularne w postaci dog|cat. Jak poprzednio perl spróbuje dopasować wyrażenie do tekstu jak najwcześniej. Na każdej pozycji zaczynając od początku tekstu perl sprubuje najpierw dopasować pierwszą alternatywę dog jeśli nie będzie pasować, perl sprawdzi na zaczynając od tego samego miejsca kolejną alternatywę cat. Jeśli cat także nie będzie pasować, wyrażenei regularne nie zostanie dopasowane więc perl przejdzie na kolejną pozycję i cała sytuacja dopasowywania się powtórzy. Przykłady:

  1. "cats and dogs" =~ /cat|dog|bird/;  # pasuje "cat"
  2. "cats and dogs" =~ /dog|cat|bird/;  # pasuje "cat"

nawet jeśli dog jest pierwszą alternatywą w drugim przykładzie, cat został dopasowany bo występuje wcześniej w tekście.


  1. "cats"  =~ /c|ca|cat|cats/; # pasuje "c"
  2. "cats"  =~ /cats|cat|ca|c/; # pasuje "cats"

W powyższym przykładzie widać, że jeśli wszystkie alternatywy pasują na tej samej pozycji w tekście, to zostanie dopasowana ta alternatywa, która zapisana jest jako pierwsza.


Grupowanie i dopasowania hierarchiczne

Metaznaki grupowania () pozwalają traktować część wyrażenia regularnego jak jedność. Część wyrażenia jest grupowana przez zamknięcie jej w nawiasach. Wyrażenie regularne house(cat|keeper) zostanie dopasowane w przypadku wystąpienia wyrazu house z przyrostkiem cat lub keeper. Kilka przykładów:

  1. /(a|b)b/;    # pasuje 'ab' lub 'bb'
  2. /(^a|b)c/;   # pasuje 'ac' na początku tekstu 'bc' gdziekolwiek


  1. /house(cat|)/;      # pasuje 'housecat' lub 'house'
  2. /house(cat(s|)|)/;  # pasuje 'housecats' lub 'housecat' lub
  3.                     # 'house'.  Zwróć uwagę, że grupy mogą być zagnieżdżone.


  1. "20" =~ /(19|20|)\d\d/;  # pasuje pusta alternatywa '()\d\d',
  2.                          # ponieważ '20\d\d' nie mogło zostać dopasowane


Wyciąganie dopasowanych

/Extracting matches


Metaznaki grupowania () pozwalają także na wyciągnięcie kawałka tekstu pasującego do grupy. Każda dopasowana grupa jest zapisywana w osobnej zmiennej, $1, $1 itd. Mogą być one używane jak wszystkie inne normalne zmienne:

  1. $czas =~ /(\d\d):(\d\d):(\d\d)/;  # pasuje godzina zapisana w formacie hh:mm:ss
  2. $godziny = $1;
  3. $minuty = $2;
  4. $seundy = $3;

W kontekście listy, dopasowanie /wyrażenia/ zawierającego grupy zwróci listę dopasowanych wartości ($1,$2,...). Dlatego powyższy przykład można zapisać jako:

  1. ($godziny, $minuty, $seundy) = ($czas =~ /(\d\d):(\d\d):(\d\d)/);


Jeśli grupy w wyrażeniu regularnym są zagnieżdżone $1 przyjmie wartość dopasowaną do grypy zaczynającej się najwcześniejszym od lewej strony nawiasem otwierającym, $2 wartość grupy zaczynającej się kolejnym nawiasem otwierającym itd. Poniższy przykład prezentuje skomplikowane wyrażenie regularne, w linii 2 napisane są numery zmiennych otrzymujących wartości:

  1. /(ab(cd|ef)((gi)|j))/;
  2.  1  2      34


Jeśli w wyrażeniu regularnym do zmiennych $1, $2 zostały przypisane wartości mogą one zostać użyte w tym samym wyrażeniu przez zapis \1, \2. Na przykład:

  1. /(\w\w\w)\s\1/; # znajduje w tekście ciągi znaków jak 'the the', 'nie nie' itp.

Zapis $1, $2, ... powinny być używane jedynie poza wyrażeniem regularnym, natomiast \1, \2, ... jedynie wewnątrz wyrażeń.


Powtórzenia

Metaznaki kwantyfikatorów ?, *, +, i {} pozwalają określić ilość powtórzeń części wyrażenia regularnego. Kwantyfikatory umieszcza się zaraz po znaku, klasie znakowej lub grupie, której chcemy ustalić ilość powtórzeń. Kwantyfikatory mają następujące znaczenia:

  • a? = dopasuj gdy 'a' występuje 1 lub 0 razy
  • a* = dopasuj gdy 'a' występuje 0 lub więcej razy, czyli dowolna ilość powtórzeń
  • a+ = dopasuj gdy 'a' występuje 1 lub więcej razy, czyli przynajmniej raz
  • a{n,m} = dopasuj gdy 'a' występuje nie mniej niż 'n' razy i nie więcej niż 'm' razy
  • a{n,} = dopasuj gdy 'a' nie mniej niż 'n' razy
  • a{n} = dopasuj gdy 'a' występuje dokładnie 'n' razy

Poniżej kilka przykładów:

  1. /[a-z]+\s+\d*/;  # pasuje dowolne słowo zapisane małymi literami, po którym występuje
  2.                  # przynajmniej jeden biały znak, po którym jest dowolny ciąg cyfr
  3. /(\w+)\s+\1/;    # pasuje każdy zdublowany alfanumeryczny ciąg znaków rozdzielony białym znakiem
  4. $rok =~ /\d{2,4}/;     # pasuje gdy rok składa się z przynajmniej 2 cyfr, ale nie więcej niż z 4
  5. $rok =~ /\d{4}|\d{2}/; # pasuje rok zapisany  w postaci 2 lub 4 cyfrowej


Kwantyfikatory próbują dopasować do siebie tyle tekstu ile się da aby wyrażenie regularne było spełnione:

  1. $x = 'the cat in the hat';
  2. $x =~ /^(.*)(at)(.*)$/; # pasuje,
  3.                         # $1 = 'the cat in the h'
  4.                         # $2 = 'at'
  5.                         # $3 = ''   (nic nie jest dopasowane)

Pierwszy kwantyfikator .* "zabiera" maksymalną ilość tekstu pozostawiając tylko tyle aby wyrażenie było nadal spełnione. Kolejna grupa w tym przypadku dopasowuje pozostałą część, dlatego ostatnia z nich (.*) zostaje dopasowana 0 razy (co jest zgodne z kwantyfikatorem) i nie zwraca ona wartości.

More matching

/Więcej dopasowań


Search and replace

/Znajdź i zmień


The split operator

/Operator podziału


AUTHOR AND COPYRIGHT

Copyright (c) 2000 Mark Kvale All rights reserved.

This document may be distributed under the same terms as Perl itself.

inne



Ten artykuł jest tylko zalążkiem.
Możesz pomóc poprzez rozszeszenie tego artykułu.

Jest to nieoficjalne tłumaczenie oficjalnej dokumentacji dostępnej na stronie http://perldoc.perl.org/perlrequick.html

Osobiste
Kategorie główne
Reklamy
Zaprzyjaźnione strony