c ++中的STD正则表达式

时间:2015-12-28 14:07:24

标签: c++ regex

我正在使用std::regex,但必须有一些我做错了。我有这样的字符串:

  

127.27.18.4_2.125.2.365.24.2_10

我必须在“_”之前取第一个字段,它是一个ip,第二个是snmp OID,最后一个是轮询时间。这些是我的模式:

\\d+\\.\\d+\\.\\d+\\.\\d+_(\\d+\\.)(\\d+\\.*)+_\\d+
\\d+\\.\\d+\\.\\d+\\.\\d+
_(\\d+\\.)(\\d+\\.*)+_

对于最后一个,我只是从字符串末尾开始搜索一个数字。

这是我的代码:

string generalCast = "\\d+\\.\\d+\\.\\d+\\.\\d+_(\\d+\\.)(\\d+\\.*)+_\\d+";
string input = "";
string ip = "";

if (regex_match(input, regex(generalCast)))
{
    string ipCast = "\\d+\\.\\d+\\.\\d+\\.\\d+";
    string oidCast = "_(\\d+\\.)(\\d+\\.*)+_";

    string oid = "";
    string polling = "";

    smatch matches;
    if (regex_match(input, matches, regex(ipCast)))
    {
        ip = matches[0];
        oid = "Error, bad OID: " + input;

        if (regex_match(input, matches, regex(oidCast)))
        {
            oid = regex_replace((string)matches[0], regex("_"), "");

            regex_match(input.cend(), input.cbegin(), matches, regex("\\d+"));
            if (matches.length() > 0)
            {
                polling = matches[0];
            }
        }
    }
}

案例是程序从第一个if开始,但在第二个我只询问ip时,它不匹配。 我习惯于使用.Net中的正则表达式和类似的工作。

我做错了什么?

我需要使用RE,因为我需要知道字段何时出错。在我使用之前:s​​tringstream和getlines。

1 个答案:

答案 0 :(得分:2)

如果您坚持使用代码,这里有一个固定的代码段:

string generalCast = R"(\d+\.\d+\.\d+\.\d+_(\d+\.)(\d+\.*)+_\d+)";
string input = "127.27.18.4_2.125.2.365.24.2_10";
string ip = "";

if (regex_match(input, regex(generalCast)))
{
    string ipCast = R"(\d+\.\d+\.\d+\.\d+)";
    string oidCast = R"(_(\d+\.)(\d+\.*)+_)";

    string oid = "";
    string polling = "";
    std::cout << "string object matched\n";
    smatch matches;
    if (regex_search(input, matches, regex(ipCast)))
    {
        std::cout << "ipCast matched: " << matches[0] << "\n";
        ip = matches[0];
        oid = "Error, bad OID: " + input;
        smatch matches1;
        if (regex_search(input, matches1, regex(oidCast)))
        {
            std::cout << "oidCast matched\n";
            oid = regex_replace((string)matches1[0], regex("_"), "");
            std::cout << "oid: " << oid << "\n";

            smatch matches2;
            regex_search(input, matches2, regex(R"(\d+$)"));
            if (matches2.length() > 0)
            {
                polling = matches2[0];
                std::cout << "Polling: " << polling << "\n";
            }
        }
    }
}

请参阅IDEONE demo

事情发生了变化:

  • 您需要每次在每个区块中声明smatch,您无法重复使用
  • 您只需要在开头使用regex_match(因为它需要完整的字符串匹配),然后,您需要使用regex_search,因为它允许部分匹配
  • \d+正则表达式会为您提供第一个数字序列,而不是最后一个(因此,您需要\d+$正则表达式。)
  • 在定义正则表达式时,使用原始字符串(R"(...)")更实用。

如果你问我,我会使用以下内容(使用捕获机制):

string generalCast = R"((\d+(?:\.\d+){3})_(\d+(?:\.\d+)+)_(\d+))";
string input = "127.27.18.4_2.125.2.365.24.2_10";
std::regex rx(generalCast);
smatch m;
if (std::regex_match(input, m, rx)) {
    std::cout << m[1].str() <<"\n";
    std::cout << m[2].str() <<"\n";
    std::cout << m[3].str() <<"\n";
}

请参阅another IDEONE demo

结果:

127.27.18.4
2.125.2.365.24.2
10

正则表达式(应与整个字符串匹配)表示:

  • (\d+(?:\.\d+){3}) - 一个或多个数字,后跟3次. + 1位或更多位数
  • _ - 文字_
  • (\d+(?:\.\d+)+) - 一个或多个数字后跟一个或多个. + 1个或更多个数字
  • _ - 文字_
  • (\d+) - 最后一位或多位数字