问题
Perl has the e regex modifier which allows Perl code rather than just a string to formulate the replacement: http://perldoc.perl.org/perlretut.html#Search-and-replace Though that example is not the greatest as there are switches to accomplish this. For those of you who understand Perl here's an example that makes more sense:
$string = "StackOverflow user: Jonathan Mee";
$string =~ s/:\s*(.*)$/$1 == "Jonathan Mee" ? ": ".$1." is AWESOME!" : ": ".$1." is ???"/e;
print $string; #Will print "StackOverflow user: Jonathan Mee is AWESOME!"
Is there a regex_replace variant in C++ that will allow me to do something similar? As in code inline for the replacement.
回答1:
regex_replace has 6 different overloads. The fmt argument is used the same way for each of them:
A string with the replacement for each match. This may include format specifiers and escape sequences that are replaced by the characters they represent.
Each of the 6 overloads also sport a flags argument which is used to control, "how fmt is formatted." The fmt related options are:
format_default: Default formatting
Uses the standard formatting rules to replace matches (those used by ECMAScript's replace method).format_sedsed formatting
Uses the same rules as the sed utility in POSIX to replace matches.format_no_copyNo copy
The sections in the target sequence that do not match the regular expression are not copied when replacing matches.format_first_onlyFirst only
Only the first occurrence of a regular expression is replaced.
Note that none of the fmt overloads, nor the flags support in-line code. So the answer is: No, there is no variant of regex_replace that supports in-line code.
However if you were willing to use a STD algorithm in conjunction with regex_iterator, you could use a lambda to accomplish in-line code.
const string foo("StackOverflow user: Jonathan Mee");
vector<string> bar;
transform(regex_iterator<string::const_iterator>(foo.cbegin(), foo.cend(), regex(".*:\\s*(.*)")),
regex_iterator<string::const_iterator>(),
back_inserter(bar),
[](const smatch& i){auto result = i.str();
if (!result.empty()){
result += (i.str(1) == "Jonathan Mee" ? " is AWESOME!" : " is ???");
}
return result;});
As you can see a lambda is usable in the transform taking in the current regex_iterator's smatch. This is very extensible to multi-line strings, in the example of string foo("StackOverflow user: Jonathan Mee\nStackOverflow user: user0"); the output would be:
StackOverflow user: Jonathan Mee is AWESOME!
StackOverflow user: user0 is ???
Clearly there are some trade-offs working with just an smatch versus regex_replace. Where str(1) falls within str() is not specified. Here I take advantage of the fact that it is right at the end of foo rather than somewhere that has to be found in the middle of foo. But it should be mentioned that the same difficulty befalls Perl's e-modifier, so I think this is pretty much on par.
来源:https://stackoverflow.com/questions/29367546/is-there-a-variant-of-regex-replace-that-supports-inline-code