Versionsnummer mit regex extrahieren
-
Hi,
nun hab ich mich schon ein bisschen in regex eingelesen und frage mich, ob ich auch einen Teil eines Strings damit extrahieren kann. Mir geht es dabei um eine Versionsangabe in der Form:
V1.5.11
Diese beinhaltet drei Informationen: die 1, die 5 und die 11. Kann ich die (einzeln natürlich) mit regex aus dem String extrahieren?
-
Da hat irgendjemand neulich mal diesen Link angegeben, den ich seitdem zu schätzen weiß:
http://txt2re.com/Demzufolge:
// URL that generated this code: // http://txt2re.com/index-c++.php3?s=V1.5.11&6&7&4 #include <stdlib.h> #include <string> #include <iostream> #include <pme.h> int main() { std::string txt="V1.5.11"; std::string re1=".*?"; // Non-greedy match on filler std::string re2="(\\d+)"; // Integer Number 1 std::string re3=".*?"; // Non-greedy match on filler std::string re4="(\\d+)"; // Integer Number 2 std::string re5=".*?"; // Non-greedy match on filler std::string re6="(\\d+)"; // Integer Number 3 PME re(re1+re2+re3+re4+re5+re6,"gims"); int n; if ((n=re.match(txt))>0) { std::string int1=re[1].c_str(); std::string int2=re[2].c_str(); std::string int3=re[3].c_str(); std::cout << "("<<int1<<")"<<"("<<int2<<")"<<"("<<int3<<")"<< std::endl; } } //----- // C++ does not provide a regular expression feature as standard. // // To run this code you will need to first download and install // the PCRE library from http://www.pcre.org/ and // the PME library from ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/Contrib/ // // Note that on Linux systems PCRE is often already installed in /usr/lib/libpcre* or /usr/local/lib/libpcre*. // // Compile and run on Unix using // # c++ x.cpp -lpme -lpcre // # ./a.out //
-
Da hab ich mich wohl schlecht ausgedrückt. Ich such weniger die Expression (aber trotzdem danke für den Link) als mehr die Methode von boost::regex, die soetwas kann. Und wie ich sie benutze. Die Expression krieg ich schon zusammen
-
Du kannst regex_match ein match_results-Objekt übergeben, das sich die submatches merkt. Die kriegst du in Stringform und kannst sie beispielsweise per Stringstream in das umwandeln, was du brauchst. Beispiel:
#include <boost/regex.hpp> #include <iostream> #include <string> int main() { boost::regex rex("V (\\d+)\\.(\\d+)\\.(\\d+)"); std::string ver = "V 5.1.1"; boost::smatch m; if(boost::regex_match(ver, m, rex)) std::cout << m[1] << std::endl << m[2] << std::endl << m[3] << std::endl; }
-
Als Ergänzung: Die Submatches entsprechen den Teilausdrücken, die durch runde Klammern im Regex-String gekennzeichnet sind.
Eine Alternativmöglichkeit zur Extraktion stellt
regex_iterator
dar (hier aber komplizierter).
-
Man könnte sich auch überlegen, das Ganze mit Boost.Xpressive zu machen und einen Teil der Arbeit dem Compiler zuzuschieben. Etwa
#include <boost/xpressive/xpressive.hpp> #include <boost/xpressive/regex_actions.hpp> #include <string> #include <iostream> int main() { using namespace boost::xpressive; unsigned major, minor, revision; std::string s = "v1.5.1"; sregex const rex = icase(as_xpr('v')) >> (+_d) [ ref(major ) = as<unsigned>(_) ] >> '.' >> (+_d) [ ref(minor ) = as<unsigned>(_) ] >> '.' >> (+_d) [ ref(revision) = as<unsigned>(_) ]; smatch m; if(regex_match(s, m, rex)) { std::cout << major + minor + revision << std::endl; } }
-
Da find ich dein erstes Beispiel schicker.
-
seldon schrieb:
Du kannst regex_match ein match_results-Objekt übergeben, das sich die submatches merkt. Die kriegst du in Stringform und kannst sie beispielsweise per Stringstream in das umwandeln, was du brauchst. Beispiel:
#include <boost/regex.hpp> #include <iostream> #include <string> int main() { boost::regex rex("V (\\d+)\\.(\\d+)\\.(\\d+)"); std::string ver = "V 5.1.1"; boost::smatch m; if(boost::regex_match(ver, m, rex)) std::cout << m[1] << std::endl << m[2] << std::endl << m[3] << std::endl; }
Das funktioniert so schon ganz gut. Kann ich denn mit einer Abfrage auch Versionen mit nur einer ("V1"), zwei ("V1.1") oder drei ("V1.1.1") Stellen abfragen?
Und dann vielleicht über die Anzahl der Matches feststellen, wie viele Stellen die Versionsangabe hat?Ich hab da sowas gefunden:
regex ex("V(\\d+)(\\.(\\d+)){0,2}");
Aber dann bekomm ich halt bei V1.2.3 die Treffer "1",".2","2",".3" und "3". Die mit dem führenden Punkt möcht ich aber nicht...