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, |