Is There a Variant of regex_replace that Supports Inline Code?

扶醉桌前 提交于 2019-12-12 03:08:02

问题


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_sed sed formatting
    Uses the same rules as the sed utility in POSIX to replace matches.
  • format_no_copy No copy
    The sections in the target sequence that do not match the regular expression are not copied when replacing matches.
  • format_first_only First 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!