I am trying to select the )9 in the string ss,
to replace it with )*9
I am getting an unhandled expression error at the 2nd line (def of ee).
I have tried all the combinations of line 2 I can think of (including double escaping the d).
std::string ss ("1 + (3+2)9 - 2 ");
std::regex ee ("(\\)\d)([^ ]");
std::string result;
std::regex_replace (std::back_inserter(result), ss.begin(), ss.end(), ee, "*$2");
std::cout << result;
You need to escape all your backslashes:
"(\\)\\d)([^ ]"
Otherwise you could be sending a control character to the regex, not the two characters \ and d.
Also, you either need a regex backslash for the second (:
"(\\)\\d)\\([^ ]"
or you need to add a matching close-parenthesis:
"(\\)\\d)([^ ])"
Related
This question already has answers here:
std::regex escape special characters for use in regex
(3 answers)
Closed 6 years ago.
Say you have a string which is provided by the user. It can contain any kind of character. Examples are:
std::string s1{"hello world");
std::string s1{".*");
std::string s1{"*{}97(}{.}}\\testing___just a --%#$%# literal%$#%^"};
...
Now I want to search in some text for occurrences of >> followed by the input string s1 followed by <<. For this, I have the following code:
std::string input; // the input text
std::regex regex{">> " + s1 + " <<"};
if (std::regex_match(input, regex)) {
// add logic here
}
This works fine if s1 did not contain any special characters. However, if s1 had some special characters, which are recognized by the regex engine, it doesn't work.
How can I escape s1 such that std::regex considers it as a literal, and therefore does not interpret s1? In other words, the regex should be:
std::regex regex{">> " + ESCAPE(s1) + " <<"};
Is there a function like ESCAPE() in std?
important I simplified my question. In my real case, the regex is much more complex. As I am only having troubles with the fact the s1 is interpreted, I left these details out.
You will have to escape all special characters in the string with \. The most straightforward approach would be to use another expression to sanitize the input string before creating the expression regex.
// matches any characters that need to be escaped in RegEx
std::regex specialChars { R"([-[\]{}()*+?.,\^$|#\s])" };
std::string input = ">> "+ s1 +" <<";
std::string sanitized = std::regex_replace( input, specialChars, R"(\$&)" );
// "sanitized" can now safely be used in another expression
I have about writing regexes in C++. I have 2 regexes which work fine in java. But these throws an error namely
one of * + was not preceded by a valid regular expression C++
These regexes are as follows:
regex r1("^[\s]*{[\s]*\n"); //Space followed by '{' then followed by spaces and '\n'
regex r2("^[\s]*{[\s]*\/\/.*\n") // Space followed by '{' then by '//' and '\n'
Can someone help me how to fix this error or re-write these regex in C++?
See basic_regex reference:
By default, regex patterns follow the ECMAScript syntax.
ECMAScript syntax reference states:
characters:
\character
description: character
matches: the character character as it is, without interpreting its special meaning within a regex expression.
Any character can be escaped except those which form any of the special character sequences above.
Needed for: ^ $ \ . * + ? ( ) [ ] { } |
So, you need to escape { to get the code working:
std::string s("\r\n { \r\nSome text here");
regex r1(R"(^\s*\{\s*\n)");
regex r2(R"(^\s*\{\s*//.*\n)");
std::string newtext = std::regex_replace( s, r1, "" );
std::cout << newtext << std::endl;
See IDEONE demo
Also, note how the R"(pattern_here_with_single_escaping_backslashes)" raw string literal syntax simplifies a regex declaration.
I want to find the number between [/ and ] (12345 in this case).
I have written such code:
float num;
string line = "A111[/12345]";
boost::regex e ("[/([0-9]{5})]");
boost::smatch match;
if (boost::regex_search(line, match, e))
{
std::string s1(match[1].first, match[1].second);
num = boost::lexical_cast<float>(s1); //convert to float
cout << num << endl;
}
However, I get this error: The error occurred while parsing the regular expression fragment: '/([0-9]{5}>>>HERE>>>)]'.
You need to double escape the [ and ] that special characters in regex denoting character classes. The correct regex declaration will be
boost::regex e ("\\[/([0-9]{5})\\]");
This is necessary because C++ compiler also uses a backslash to escape entities like \n, and regex engine uses the backslash to escape special characters so that they are treated like literals. Thus, backslash gets doubled. When you need to match a literal backslash, you will have to use 4 of them (i.e. \\\\).
Use the following (escape [ and ] because they are special characters in regex meaning a character class):
\\[/([0-9]{5})\\]
^^ ^^
The following code is intended to convert the )9 in the first line to a )*9.
The original string is printed unmodified by the last line.
std::string ss ("1 + (3+2)9 - 2 ");
std::regex ee ("(\\)\\d)([^ ]");
std::string result;
std::regex_replace (std::back_inserter(result), ss.begin(), ss.end(), ee, ")*$2");
std::cout << result;
This is based on a very similar example at: http://www.cplusplus.com/reference/regex/regex_replace/
MS Visual Studio Express 2013.
I see two issues: first, your capture group should only include the '9' portion of the string, and second the group you want to use for replacement is not $2, but $1:
std::string ss ("1 + (3+2)9 - 2 ");
static const std::regex ee ("\\)(\\d)");
std::string result;
std::regex_replace (std::back_inserter(result), ss.begin(), ss.end(), ee, ")*$1");
std::cout << result;
Output:
1 + (3+2)*9 - 2
Live Demo
Edit
It appears that you want a more general replacement.
That is, wherever there is a number followed by an open paren, e.g 1( or a close paren followed by a number, e.g. )1. You want an asterisk between the number and the paren.
In C++ we can do this with regex_replace, but we need two of them at this time of writing. We can kind of chain them together:
std::string ss ("1 + 7(3+2)9 - 2");
static const std::regex ee ("\\)(\\d+)");
static const std::regex e2 ("(\\d+)\\(");
std::string result;
std::regex_replace (std::back_inserter(result), ss.begin(), ss.end(), ee, ")*$1");
result = std::regex_replace (result, e2, "$1*(");
std::cout << result;
Output:
1 + 7*(3+2)*9 - 2
Live Demo2
Edit 2
Since you asked in another question how to turn this into one that can also capture spaces, here is a slight modification to handle possible spaces between the number and paren chars:
static const std::regex ee ("\\)\\s*(\\d+)");
static const std::regex e2 ("(\\d+)\\s*\\(");
Live Demo3
When reading line by line i call this function on each line looking for function calls(names). I use this function to match the any valid characters a-z 0-9 and _ with '('. My problem is i do not understand fully the c++ style regex and how to get it to look through the entire line for possible matches?. This regex is simple and strait forward just does not work as expected but im learning this is the c++ norm.
void readCallbacks(const std::string lines)
{
std::string regxString = "[a-z0-9]+\(";
regex regx(regxString, std::regex_constants::icase);
smatch result;
if(regex_search(lines.begin(), lines.end(), result, regx, std::regex_constants::match_not_bol))
{
cout << result.str() << "\n";
}
}
You need to escape the backslash or use a raw string literal:
std::regex pattern("[a-z0-9]+\\(", std::regex_constants::icase);
// ^^
std::regex pattern(R"([a-z0-9]+\()", std::regex_constants::icase);
// ###^^^^^^^^^^^##
Also, your character range doesn't contain the desired underscore (_).