【问题标题】:C++ boost regex replace with conditionsC++ boost 正则表达式替换为条件
【发布时间】:2016-12-27 19:48:05
【问题描述】:

上下文:

我目前正在用 C++ 编写日期格式库。例如。该库接受一个格式化字符串,例如:dddd, mmmm d, dddd yyyy 并产生一个结果 Tuesday, December 26, Tuesday 2016 给定年份:2016,月份:12,日期:26(dddd 代表工作日,d 代表数字日期,@ 987654326@ 代表月份,yyyy 代表年份)。

我想通过使用boost::regex_replace 来实现这一点。

我尝试过的:

Javascript


javascript 我可以很容易地做到这一点:

var pattern = 'dddd, mmmm d, yyyy';
pattern.replace(/(dddd)|(d)|(mmmm)|(yyyy)/gi, function (dddd, d, mmmm, yyyy){
    if (dddd) {
        return 'Tuesday';
    }

    if (d) {
        return '26'
    }

    if (mmmm) {
        return 'December';
    }

    if (yyyy) {
       return '2016';
    }
    return '';
}

C++


boost::regex regex1("(dddd)");
boost::regex regex2("(d)");
boost::regex regex3("(mmmm)");
boost::regex regex4("(yyyy)");
boost::smatch match;

// dddd
if (boost::regex_search(pattern, match, regex1))
{
    pattern = boost::regex_replace(pattern, regex1, "Tuesday");
}

// d
if (boost::regex_search(pattern, match, regex2))
{
    pattern = boost::regex_replace(pattern, regex2, "26");
}

// mmmm
if (boost::regex_search(pattern, match, regex3))
{
        pattern = boost::regex_replace(pattern, regex3, "December");
}

// yyyy
if (boost::regex_search(pattern, match, regex4))
{
    pattern = boost::regex_replace(pattern, regex4, "2016");
}

但是,这给了我"Tues26ay, December 26, Tues26ay 2016" 的结果。原因是:一旦我将模式dddd 替换为TuesdayTuesday 内部的d 就成为regex2 的目标模式,导致它被26 替换。

我不确定如何解决此问题,或者我认为我解决此问题的 C++ 方法不正确。是否有可能在 C++ boost::regex 中有类似于 Javascript 的东西?

任何帮助将不胜感激!

【问题讨论】:

标签: c++ regex boost


【解决方案1】:

我不知道你为什么不按字面意思进行一对一翻译:

Live On Coliru

#include <boost/regex.hpp>
#include <iostream>

int main() {
    std::string pattern = "dddd, mmmm d, yyyy";
    pattern = boost::regex_replace(pattern, boost::regex("(dddd)|(d)|(mmmm)|(yyyy)"), [](auto& match)->std::string{
        if (match.str() == "dddd")
            return "Tuesday";

        if (match.str() == "d")
            return "26";

        if (match.str() == "mmmm")
            return "December";

        if (match.str() == "yyyy")
            return "2016";

        return "";
    });

    std::cout << "Result: " << pattern << "\n";
}

打印

Result: Tuesday, December 26, 2016

奖金:

【讨论】:

  • 太棒了!也感谢替代版本!你认为有可能获得匹配的索引以便可以使用开关吗?
  • 您可以根据需要进行设置,但默认情况下不存在。毕竟,匹配不需要是排他性的(想想"(d(ddd))"
  • @PatLaugh 将最高匹配组索引传递给回调in c++11c++14 的变体;这是另一个solution that uses four arguments to the formatter callback
【解决方案2】:

一个简单的解决方案是用一个肯定不会在其他地方的控制字符替换工作日,然后最后用适当的工作日替换它;我没有 boost,但它适用于 std::regex。

添加/修改:

boost::regex regex5("(\x01)");
//dddd
pattern = regex_replace(pattern, regex1, "\x01");
//then the fifth check
pattern = regex_replace(pattern, regex5, "Tuesday");

【讨论】:

  • 是的,应该可以按预期进行。实际上,当我在等待答案时,我想出了与您类似的想法,只是您的想法通过使用控制字符作为占位符更安全。我会将其标记为已接受的答案。谢谢。
  • 有趣的是,您可以像在 javascript 中一样为替换格式化程序使用回调。看我的回答
猜你喜欢
  • 1970-01-01
  • 2012-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-25
  • 1970-01-01
  • 1970-01-01
  • 2019-02-07
相关资源
最近更新 更多