是否有支持内联代码的regex_replace的变体?

时间:2015-03-31 11:25:51

标签: c++ regex perl replace substitution

Perl具有e正则表达式修饰符,它允许使用Perl代码而不仅仅是字符串来表示替换:http://perldoc.perl.org/perlretut.html#Search-and-replace尽管该示例并不是最好的,因为有切换来实现此目的。对于那些了解Perl的人来说,这是一个更有意义的例子:

$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!"

C ++中是否有regex_replace变体允许我做类似的事情?如代码内联替换。

1 个答案:

答案 0 :(得分:0)

regex_replace有6种不同的重载。 fmt参数对每个参数的使用方式相同:

  

替换每场比赛的字符串。   这可能包括格式说明符和转义序列,它们由它们代表的字符替换。

6个重载中的每一个也都带有flags参数,用于控制,{#1}} fmt的格式。" fmt相关选项包括:

  • format_default:默认格式


    使用标准格式规则来替换匹配(ECMAScript&替换方法使用的那些)。
  • format_sed sed格式化 使用与POSIX中的sed实用程序相同的规则来替换匹配。
  • format_no_copy没有副本
    替换匹配时,不会复制目标序列中与正则表达式不匹配的部分。
  • format_first_only首先只有 只替换第一次出现的正则表达式。

请注意,fmt重载和flags都不支持内联代码。所以答案是:不,没有regex_replace的变体支持内联代码。


但是,如果您愿意将STD算法与regex_iterator结合使用,则可以使用lambda来完成内联代码。

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;});

正如您所看到的,transform接收当前regex_iterator smatch时可以使用lambda。这对于多行字符串是非常可扩展的,在string foo("StackOverflow user: Jonathan Mee\nStackOverflow user: user0");的示例中,输出将是:

  

StackOverflow用户:Jonathan Mee真棒!   StackOverflow用户:user0是???

显然,只有smatchregex_replace进行权衡。 str(1)落在str()范围内的位置未指定。在这里,我利用它在foo的末尾,而不是必须在foo的中间找到的地方。但应该提到Perl的e - 修饰符同样存在困难,所以我认为这几乎是相同的。