Różnice między wybraną wersją a wersją aktualną.
| Both sides previous revision Previous revision | |||
|
regex [2008/04/17 00:19] przemoc wersja prefinal |
regex [2008/04/17 03:03] (aktualna) przemoc wersja finalna |
||
|---|---|---|---|
| Linia 80: | Linia 80: | ||
| | | alternatywa | | | alternatywa | ||
| [znaki^odrzuty] | dopuszczalny znaki i niedopuszczalne odrzuty | [znaki^odrzuty] | dopuszczalny znaki i niedopuszczalne odrzuty | ||
| + | \< \> \b | początek, koniec słowa i którekolwiek z nich | ||
| \d <=> [[:digit:]] | cyfra | \d <=> [[:digit:]] | cyfra | ||
| \l <=> [[:lower:]] | mała litera | \l <=> [[:lower:]] | mała litera | ||
| Linia 91: | Linia 92: | ||
| \W <=> [^[:word:]] | nie :znak "słowny" | \W <=> [^[:word:]] | nie :znak "słowny" | ||
| (?#komentarz) | ignorowany (komentarz) | (?#komentarz) | ignorowany (komentarz) | ||
| - | (?:wzorzec) | "zjada" 0 znaków tylko jeżeli wzorzec się zgadza | + | (?=wzorzec) | "zjada" 0 znaków tylko jeżeli wzorzec się zgadza |
| (?!wzorzec) | "zjada" 0 znaków tylko jeżeli wzorzec nie pasuje | (?!wzorzec) | "zjada" 0 znaków tylko jeżeli wzorzec nie pasuje | ||
| Linia 107: | Linia 108: | ||
| #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'. | + | 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 266: | Linia 267: | ||
| // Wyrażenie regularne zgodne z formatem IBAN | // Wyrażenie regularne zgodne z formatem IBAN | ||
| // IBAN = International Bank Account Number | // 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}"); | + | 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 | // Sprawdź czy string ma format IBAN | ||
| Linia 308: | Linia 309: | ||
| 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> | ||
| + | |||
| + | Prosty przykład użycia korzystający również z iteratora po wszystkich dopasowaniach wyrażenia regularnego. | ||
| + | <code cpp> | ||
| + | #include <iostream> | ||
| + | #include <string> | ||
| + | #include <boost/regex.hpp> | ||
| + | |||
| + | // Callback dla funkcji std::for_each operujący na wynikach dopasowania. | ||
| + | bool printRep(const boost::smatch& what) | ||
| + | { | ||
| + | std::cout << what[1] << " "; // Wyświetl na standardowe wyjście pierwsze podwyrażenie. | ||
| + | return true; // Nie zatrzymuj wykonywania pętli for_each. | ||
| + | } | ||
| + | |||
| + | // Wczytaj linię z wejścia i sprawdź czy są w niej powtórzenia "słów", | ||
| + | // a jeżeli są, podaj jakie. | ||
| + | int main() { | ||
| + | // Wyrażenie regularne reprezentujące powtarzające się słowa. | ||
| + | boost::regex rep("(\\<\\w+\\>)(?:\\s+\\<\\1\\>)+"); | ||
| + | std::string line; | ||
| + | std::getline(std::cin, line); | ||
| + | // Początkowy iterator dopasowań do wyrażen regularnych. | ||
| + | boost::sregex_iterator begin(line.begin(), line.end(), rep); | ||
| + | // Terminalny iterator dopasowań do wyrażen regularnych. | ||
| + | boost::sregex_iterator end; | ||
| + | // Dla każdego dopasowania wywołaj funkcję printRep. | ||
| + | std::for_each(begin, end, &printRep); | ||
| + | std::cout << std::endl; | ||
| + | return 0; | ||
| + | } | ||
| </code> | </code> | ||
| Linia 328: | Linia 360: | ||
| const basic_string<charT>& fmt, | const basic_string<charT>& fmt, | ||
| match_flag_type flags = match_default); | match_flag_type flags = match_default); | ||
| + | </code> | ||
| + | |||
| + | W domyślnej składni stringu formatującego (przy braku flagi ''regex_constants:literal'') zdefiniowane są sekwencje specjalne odnoszące się do podmienianego dopasowania takie jak w Perlu (zaprezentowane zostały wcześniej w tabelce [[#Dopasowania]]). Aby uzyskać na wyjściu znak dolara ($), trzeba napisać go dwukrotnie. | ||
| + | |||
| + | Jako przykład zastosowania przedstawię kod aplikacji wyświetlającej na wyjście przekazany w 1. argumencie plik CSV (Comma-Separated Values) z zamienionymi miejscami pierwszymi dwiema kolumnami, a kolumny te są oddzielone przecinkiem. | ||
| + | <code cpp> | ||
| + | #include <iostream> | ||
| + | #include <fstream> | ||
| + | #include <string> | ||
| + | #include <boost/regex.hpp> | ||
| + | |||
| + | // Załaduj strumień wejściowy do stringa. | ||
| + | void loadFile(std::string& s, std::istream& is) | ||
| + | { | ||
| + | s.erase(); | ||
| + | s.reserve(is.rdbuf()->in_avail()); | ||
| + | char c; | ||
| + | while (is.get(c)) | ||
| + | { | ||
| + | if (s.capacity() == s.size()) | ||
| + | s.reserve(s.capacity() * 3); | ||
| + | s.append(1, c); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | // Wyświetl plik CSV (o nazwie przekazanej w 1. argumencie) z zamienionymi pierwszymi 2 kolumnami | ||
| + | int main(int argc, const char** argv) | ||
| + | { | ||
| + | // Wyrażenie regularne reprezentujące pierwsze dwie kolumny (druga może być pusta) | ||
| + | boost::regex re("^([^,\n]*),?([^,\n]*)"); | ||
| + | // Format stringu odpowiadający podmienianemu dopasowaniu. | ||
| + | std::string fmt("\\2,\\1"); | ||
| + | try { | ||
| + | std::ifstream fs(argv[1]); | ||
| + | std::string in; | ||
| + | loadFile(in, fs); | ||
| + | // Wyświetl na wyjściu string in z zamienionymi dopasowaniami re na string formatujący fmt. | ||
| + | std::cout << boost::regex_replace(in, re, fmt); | ||
| + | } | ||
| + | catch(...) { | ||
| + | return -1; | ||
| + | } | ||
| + | return 0; | ||
| + | } | ||
| </code> | </code> | ||
| Linia 353: | Linia 429: | ||
| }; | }; | ||
| </code> | </code> | ||
| + | |||
| + | Po 2 przykłady użycia odsyłam na sam dół strony z dokumentacją [[http://www.boost.org/doc/libs/1_35_0/libs/regex/doc/html/boost_regex/ref/regex_token_iterator.html|regex_token_iterator]]. | ||
| ===== Boost.Xpressive - relatywnie młody konkurent ===== | ===== Boost.Xpressive - relatywnie młody konkurent ===== | ||
| - | Ważne innowacje: | + | Ważne innowacje w stosunku do Boost.Regex: |
| * obsługa tworzenia (obok dynamicznych, podobnych w zapisie do Boost.Regex) statycznych wyrażeń regularnych, podobnych w zapisie do Boost.Spirit, przez przeciążanie operatorów i zastosowanie techniki zwanej szablonami wyrażeniowymi (ang. //expression templates//) - owa statyczność daje wiele możliwości, m.in. kontrolę poprawności takiego wyrażenia już w czasie kompilacji, | * obsługa tworzenia (obok dynamicznych, podobnych w zapisie do Boost.Regex) statycznych wyrażeń regularnych, podobnych w zapisie do Boost.Spirit, przez przeciążanie operatorów i zastosowanie techniki zwanej szablonami wyrażeniowymi (ang. //expression templates//) - owa statyczność daje wiele możliwości, m.in. kontrolę poprawności takiego wyrażenia już w czasie kompilacji, | ||
| * możliwość mieszania statycznych i dynamicznych wyrażeń regularnych, | * możliwość mieszania statycznych i dynamicznych wyrażeń regularnych, | ||