Here is my code:
std::string var = "(1,2)";
std::smatch match;
std::regex rgx("[0-9]+");
if(std::regex_search(var,match,rgx))
for (size_t i = 0; i < match.size(); ++i)
std::cout << i << ": " << match[i] << '\n';
I want to be able to extract both 1 AND 2, but so far output is just the first match (1). I can't seem to figure out why and my brain is fried. It's probably something obvious
regex_match's elements are for matching groups within the regex.
In a slightly modified example
std::string var = "(11b,2x)";
std::smatch match;
std::regex rgx("([0-9]+)([a-z])");
if(std::regex_search(var,match,rgx))
for (size_t i = 0; i < match.size(); ++i)
std::cout << i << ": " << match[i] << '\n';
You'd get the following output:
0: 11b
1: 11
2: b
What you want is to use std::regex_iterator to go over all the matches:
auto b = std::sregex_iterator(var.cbegin(), var.cend(), rgx);
auto e = std::sregex_iterator();
std::for_each(b, e, [](std::smatch const& m){
cout << "match: " << m.str() << endl;
});
This will yield the desired output:
match: 1
match: 2
live demo
Related
I have a regex function that parses a URL request and finds a match for an IP and port pattern. I want to push these matches into a vector and then print them out to the screen. The size of the vector prints to the screen but nothing is printed to the screen when I attempt to iterate through the vector and print the elements.
code:
std::vector<std::string> matchVector;
std::smatch m;
std::regex e ("\\/([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3})\\:?([0-9]{1,5})");
while (std::regex_search (requestURL,m,e))
{
for (auto x:m)
{
std::stringstream ss;
ss << x;
std::string str = ss.str();
matchVector.push_back(str);
std::cout << "match " << str << " ";
}
std::cout << std::endl;
requestURL = m.suffix().str();
}
std::cout << "print vector of size : " << matchVector.size()<< '\n';
//this is where nothing prints to the screen
for (int i =0; i < matchVector.size(); i++)
{
std::cout << matchVector[i];
}
current output:
match /192.xxx.111.xxx:8080 match 192.xxx.111.xxx match 8080
print vector of size : 3
std::cout is buffered, so it's not synchronized with what you see on the terminal. Try simply flushing std::cout after your print loop:
std::cout << std::flush;
hello this is pcre regex (php regex)
/\h*(.*?)\h*[=]\h*("(.*?(?:[\\\\]".*?)*)")\h*([,|.*?])/
this regex work for this string
data1 = "value 1", data2 = "value 2", data3 = " data4(" hey ") ",
and get
data, data2, data3
val, val2, data4("val3")
what is this regex equal in c++ regex ?
You should replace \h with \s and use \\ inside a raw string literal.
Refer to the following example code:
#include <string>
#include <iostream>
#include <regex>
using namespace std;
int main() {
std::string pat = R"(\s*(.*?)\s*=\s*(\"(.*?(?:[\\]\".*?)*)\")\s*([,|.*?]))";
std::regex r(pat);
std::cout << pat << "\n";
std::string s = R"(data1 = "value 1", data2 = "value 2", data3 = " data4(" hey ") ",)";
std::cout << s << "\n";
for(std::sregex_iterator i = std::sregex_iterator(s.begin(), s.end(), r);
i != std::sregex_iterator();
++i)
{
std::smatch m = *i;
std::cout << "Capture 1: " << m[1].str() << " at Position " << m.position(1) << '\n';
std::cout << "Capture 3: " << m[3].str() << " at Position " << m.position(3) << '\n';
}
return 0;
}
See IDEONE demo and a JS (ECMA5) regex demo
I feel like this is a pretty basic question but I did not find a post for it. If you know one please link it below.
So what I'm trying to do is look through a string and extract the numbers in groups of 2.
here is my code:
int main() {
string line = "P112233";
boost::regex e ("P([0-9]{2}[0-9]{2}[0-9]{2})");
boost::smatch match;
if (boost::regex_search(line, match, e))
{
boost::regex f("([0-9]{2})"); //finds 11
boost::smatch match2;
line = match[0];
if (boost::regex_search(line, match2, f))
{
float number1 = boost::lexical_cast<float>(match2[0]);
cout << number1 << endl; // this works and prints out 11.
}
boost::regex g(" "); // here I want it to find the 22
boost::smatch match3;
if (boost::regex_search(line, match3, g))
{
float number2 = boost::lexical_cast<float>(match3[0]);
cout << number2 << endl;
}
boost::regex h(" "); // here I want it to find the 33
boost::smatch match4;
if (boost::regex_search(line, match4, h))
{
float number3 = boost::lexical_cast<float>(match4[0]);
cout << number3 << endl;
}
}
else
cout << "found nothing"<< endl;
return 0;
}
I was able to get the first number but I have no idea how to get the second(22) and third(33).
what's the proper expression I need to use?
As #Cornstalks mentioned you need to use 3 capture groups and then you access them like that:
int main()
{
std::string line = "P112233";
boost::regex e("P([0-9]{2})([0-9]{2})([0-9]{2})");
boost::smatch match;
if (boost::regex_search(line, match, e))
{
std::cout << match[0] << std::endl; // prints the whole string
std::cout << match[1] << ", " << match[2] << ", " << match[3] << std::endl;
}
return 0;
}
Output:
P112233
11, 22, 33
I don't favour regular expressions for this kind of parsing. The key point being that the numbers are still strings when you're done with that hairy regex episode.
I'd use Boost Spirit here instead, which parses into the numbers all at once, and you don't even have to link to the Boost Regex library either, because Spirit is header-only.
Live On Coliru
#include <boost/spirit/include/qi.hpp>
#include <iostream>
namespace qi = boost::spirit::qi;
static qi::int_parser<int, 10, 2, 2> two_digits;
int main() {
std::string const s = "P112233";
std::vector<int> nums;
if (qi::parse(s.begin(), s.end(), "P" >> *two_digits, nums))
{
std::cout << "Parsed " << nums.size() << " pairs of digits:\n";
for(auto i : nums)
std::cout << " * " << i << "\n";
}
}
Parsed 3 pairs of digits:
* 11
* 22
* 33
std::string str = "ahw \t\n";
std::regex re(R"((\s)*)");
std::smatch mr;
if (std::regex_search(str, mr, re))
{
std::cout << "match found: " << mr.size() << "\n";
for (size_t i = 0; i < mr.size(); ++i)
{
std::string strrep = mr.str(i);
int len = mr.length(i);
std::cout << "index: " << i << "len : " << len << " string: '" << strrep << "'\n";
}
}
std::string newStr = std::regex_replace(str, re, "");
std::cout << "new string: '" << newStr << "'\n";
result:
What I expect: only 1 match, strrep should be ' \t\n', and len should be len(strrep) = 6. But both vc12 and gcc4.9.2 show the above result.
What's wrong with my understand? How could I match the whitespace sequence ' \t\n'?
Just turn \s* to \s+ in your regex because \s* matches an empty string also(ie, \s* matches zero or more spaces) also and you don't need to have a capturing group.
I am trying to use Boost regular expressions module to extract the numbers from character strings of this format: "{ 12354,21354, 123 }"
The following code has been written to this end. As I do this operation in a loop the string is stored in it->c_str():
boost::cmatch matches;
boost::regex reNumber("-*[0-9.]+");
boost::regex reFiniteValues(" *\\{.*\\} *");
std::cout << "\ttesting for finite values" << std::endl;
if (boost::regex_match(it->c_str(), matches, reFiniteValues))
{
boost::regex_search(it->c_str(), matches, reNumber);
std::cout << "matches.size(): " << matches.size() << std::endl;
for(unsigned int i = 0; i < matches.size(); ++i)
{
std::cout << matches[i] << std::endl;
}
if (matches.size() > 0)
{
std::cout << "\tpattern found" << std::endl;
continue;
}
}
However the size of the matches object is 1, and it only contains 12354 in this example. I would like to know how I can retrieve all the numbers from the string.
You could maybe try to loop regex_search(). -
typedef std::string::const_iterator SITR;
std::string str = it->c_str();
SITR start = str.begin();
SITR end = str.end();
boost::smatch m;
while ( boost::regex_search (start, end, m, reNumber ) )
{
std::cout << m[0].str() << std::endl;
start = m[0].second;
}