Narzędzia użytkownika

Narzędzia witryny


regex

Różnice

Różnice między wybraną wersją a wersją aktualną.

Odnośnik do tego porównania

Both sides previous revision Previous revision
Last revision Both sides next revision
regex [2008/04/16 16:01]
przemoc wersja preprefinalna
regex [2008/04/17 00:19]
przemoc wersja prefinal
Linia 1: Linia 1:
 ====== Wyrażenia regularne oczami programisty C++, czyli Boost.Regex ====== ====== Wyrażenia regularne oczami programisty C++, czyli Boost.Regex ======
  
-[[przemoc@gmail.com|Przemysław Pawełczyk ​G1ISI]]+__Przemysław Pawełczyk ​G1ISI__
  
 W życiu każdego programisty przychodzi czas, w którym musi poznać wyrażenia regularne (z różnych przyczyn), a znając już je, używa ich chętnie i bez oporów, przynajmniej w skryptach shellowych (a de facto w programach typu [[wp>​AWK]],​ [[wp>​grep]] czy [[wp>​sed]]) i w interpretowanych językach jak [[wp>​PHP]],​ [[wp>​Perl]],​ [[wp>​Ruby_(programming_language)|Ruby]] oraz innych. W życiu każdego programisty przychodzi czas, w którym musi poznać wyrażenia regularne (z różnych przyczyn), a znając już je, używa ich chętnie i bez oporów, przynajmniej w skryptach shellowych (a de facto w programach typu [[wp>​AWK]],​ [[wp>​grep]] czy [[wp>​sed]]) i w interpretowanych językach jak [[wp>​PHP]],​ [[wp>​Perl]],​ [[wp>​Ruby_(programming_language)|Ruby]] oraz innych.
Linia 107: Linia 107:
 #include <​boost/​regex.hpp>​ #include <​boost/​regex.hpp>​
 </​code>​ </​code>​
 +Przy linkowaniu musimy natomiast dołączyć bibliotekę Boost.Regex,​ co w systemach *nixowych odbywa się za pomocą parametru '​-lboost_regex'​.
 +
 Tak jak w przypadku innych bibliotek Boosta, wszystkie stałe, klasy i funkcje zewnętrzne znajdują się przestrzeni nazw ''​boost''​ i dla przejrzystości nie będę tego pisał przy przytaczaniu fragmentów definicji podstawowych elementów Boost.Regex. Tak jak w przypadku innych bibliotek Boosta, wszystkie stałe, klasy i funkcje zewnętrzne znajdują się przestrzeni nazw ''​boost''​ i dla przejrzystości nie będę tego pisał przy przytaczaniu fragmentów definicji podstawowych elementów Boost.Regex.
  
Linia 133: Linia 135:
 Najważniejszy jest jednak konstruktor:​ Najważniejszy jest jednak konstruktor:​
 <code cpp> <code cpp>
-explicit basic_regex(const ​ charT* p, flag_type f = regex_constants::​normal);​+explicit basic_regex(const charT* p, flag_type f = regex_constants::​normal);​
 </​code>​ </​code>​
 który przyjmuje sekwencję znaków zawierającą wyrażenie regularne oraz tryb przetwarzania tego wyrażenia. który przyjmuje sekwencję znaków zawierającą wyrażenie regularne oraz tryb przetwarzania tego wyrażenia.
 W przypadku niepoprawnego wyrażenia regularnego rzucany jest wyjątek ''​boost::​regex_error''​ (dawniej ''​boost::​bad_expression''​ lub ''​boost::​bad_pattern'',​ które są teraz aliasami do ''​boost::​regex_error''​ dla wstecznej kompatybilności),​ chyba że przekazano flagę ''​regex_constants::​no_except''​. W przypadku niepoprawnego wyrażenia regularnego rzucany jest wyjątek ''​boost::​regex_error''​ (dawniej ''​boost::​bad_expression''​ lub ''​boost::​bad_pattern'',​ które są teraz aliasami do ''​boost::​regex_error''​ dla wstecznej kompatybilności),​ chyba że przekazano flagę ''​regex_constants::​no_except''​.
  
-Mamy następujące podstawowe (nieuzależnione od wybranej składni) tryby przetwarzania):+Mamy następujące podstawowe (nieuzależnione od wybranej składni) tryby przetwarzania:​
 <code cpp> <code cpp>
 namespace regex_constants { namespace regex_constants {
Linia 184: Linia 186:
 </​code>​ </​code>​
  
-Dopasowania to tak naprawdę kolekcje poddopasowań ''​boost::​sub_match'',​ do których dostęp mamy jedynie poprzez ''​operator[]''​ klasy ''​boost::​match_results''​.+Dopasowania to tak naprawdę kolekcje poddopasowań ''​boost::​sub_match'',​ do których dostęp mamy jedynie poprzez ''​operator[]''​ klasy ''​boost::​match_results''​. Obiekt klasy ''​boost::​sub_match''​ posiada kilka przydatnych składowych:​ boolowską ''​matched''​ informującą o tym czy dane znaczone podwyrażenie brało udział w dopasowaniu i jeżeli tak, to iteratory ''​first'',​ ''​second''​ wskazujące na początek oraz koniec (z wyłączeniem) w ciągu, który pokrył to dopasowanie.
  
 +Mając obiekt tej klasy, nazwijmy go m, odwołania do poszczególnych elementów wyglądają następująco:​
 +^ Boost.Regex ^ Perl ^ Opis ^
 +| m.prefix() ​ | $`   | treść poprzedzająca dopasowanie ​ |
 +| m[0]        | $& ​  | cała dopasowana treść ​           |
 +| m[1]        | $1   | pierwsze znaczone podwyrażenie ​  |
 +|         ​... ​      || kolejne znaczone podwyrażenia ​   |
 +| m[n]        | $n   | n-te znaczone podwyrażenie ​      |
 +| m.suffix() ​ | $' ​  | treść następująca po dopasowaniu |
 +
 +Szablon klasy ''​match_results''​ posiada także metody
 +<code cpp>
 +const_iterator begin() const; ​ // Zwraca startowy iterator znaczonych podwyrażeń.
 +const_iterator end() const; ​   // Zwraca terminujący iterator znaczonych podwyrażeń.
 +</​code>​
 +które ułatwiają realizację wygodnego iterowania po znaczonych podwyrażeniach.
 +
 +Dostępne są ponadto różne tryby dopasowań, przekazywane w funkcjach niżej omówionych. Przykłady to:
 +<code cpp>
 +namespace regex_constants {
 +    typedef implemenation-specific-bitmask-type match_flag_type;​
 +    ​
 +    static const match_flag_type match_default = 0;      // Zachowanie domyślne (zgodne z ECMA-262)
 +    /* ... */
 +    static const match_flag_type match_not_null; ​        // Dopasowanie nie może być puste.
 +    /* ... */
 +    static const match_flag_type match_single_line; ​     // ^ odpowiada za początek tekstu,
 +                                                         // a $ - koniec tekstu.
 +    /* ... */    ​
 +    static const match_flag_type format_no_copy; ​        // Sekcje tekstu niepasujące do wyrażenia
 +                                                         // regularnego nie są kopiowane do
 +                                                         // wyjściowego łańcucha znaków.
 +    /* ... */
 +    static const match_flag_type format_all; ​            // Aktywuje wszystkie dostępne rozszerzenia
 +                                                         // składni, włączając w to warunkowe podstawienia.
 +}
 +</​code>​
 ===== Możliwości Boost.Regex ===== ===== Możliwości Boost.Regex =====
  
 Same szablony klas ''​boost::​basic_regex''​ oraz ''​boost::​match_results''​ byłyby nic nie warte bez funkcji, które na nich operują realizując podstawowe przypadki użycia wyrażen regularnych. ​ Same szablony klas ''​boost::​basic_regex''​ oraz ''​boost::​match_results''​ byłyby nic nie warte bez funkcji, które na nich operują realizując podstawowe przypadki użycia wyrażen regularnych. ​
  
-Poniżej omówione szablony funkcji parametryzowane są różnymi elementami w zajemności od wersji (pominę dokładne deklaracje tych szablonów),​ ale zawsze jest to m.in. typ znaku.+Poniżej omówione szablony funkcji parametryzowane są różnymi elementami w zależności od wersji (pominę dokładne deklaracje tych szablonów),​ ale zawsze jest to m.in. typ znaku.
  
 ==== Dopasowywanie (matching) - regex_match ==== ==== Dopasowywanie (matching) - regex_match ====
Linia 214: Linia 252:
                  const basic_regex<​charT,​ traits>&​ e,                  const basic_regex<​charT,​ traits>&​ e,
                  ​match_flag_type flags = match_default);​                  ​match_flag_type flags = match_default);​
 +</​code>​
 +
 +Chyba najważniejsze w tej funkcji jest to, że dopasowaniu musi ulec cały tekst, dlatego też asercje użyte na początku i końcu wyrażenia regularnego (^ i $ odpowiednio) nie mają najmniejszego znaczenia (o czym już wcześniej wspomniałem w mikropokazie).
 +
 +Najczęściej używana jest do badania poprawności przekazanych danych.
 +
 +<code cpp>
 +#include <​iostream>​
 +#include <​string>​
 +#include <​boost/​regex.hpp>​
 +
 +namespace validations {
 +    // Wyrażenie regularne zgodne z formatem IBAN
 +    // IBAN = International Bank Account Number
 +    static const boost::​regex ibanFormat("​[A-Z]{2}\\d{2} ?​[A-Z\\d]{4}( ?​\\d{4}){1,​} ?​\\d{1,​4}"​);​
 +
 +    // Sprawdź czy string ma format IBAN
 +    bool hasIbanFormat(const std::​string&​ s)
 +    {
 +        return regex_match(s,​ ibanFormat);​
 +    }    ​
 +}
 +
 +// Wczytaj linię z wejścia i sprawdź czy to może być IBAN,
 +// wówczas zwróć 1, w przeciwnym przypadku - 0.
 +int main() {
 +    std::string line;
 +    std::​getline(std::​cin,​ line);
 +    std::cout << validations::​hasIbanFormat(line) << std::endl;
 +    return 0;
 +}
 </​code>​ </​code>​
  
Linia 232: Linia 301:
                  ​match_flag_type flags = match_default);​                  ​match_flag_type flags = match_default);​
  
-// Wesja główna, wołana także przez powyższze+// Wesja główna, wołana także przez powyższe
 template <class BidirectionalIterator,​ class Allocator, class charT, class traits> template <class BidirectionalIterator,​ class Allocator, class charT, class traits>
 bool regex_search(BidirectionalIterator first, ​ bool regex_search(BidirectionalIterator first, ​
Linia 282: Linia 351:
                         match_flag_type m = match_default);​                         match_flag_type m = match_default);​
     /* ... */     /* ... */
-}+};
 </​code>​ </​code>​
  
regex.txt · ostatnio zmienione: 2008/04/17 03:03 przez przemoc