c++中的STD正则表达式

STD Regular Expressions in c++

本文关键字:正则表达式 STD 中的 c++      更新时间:2023-10-16

我正在使用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开始执行,但在第二个if中,当我只要求ip时,它不匹配。我习惯于在.Net中使用正则表达式,以及类似的东西。

我做错了什么?

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

如果你坚持你的代码,这里有一个固定的片段:

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 matchedn";
    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 matchedn";
            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演示

事情发生了变化:

  • 您需要在每个块中每次声明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";
}

查看另一个IDEONE演示

结果:

127.27.18.4
2.125.2.365.24.2
10

正则表达式(应该与整个字符串匹配)的意思是:

  • (d+(?:.d+){3})-1个或多个数字,然后出现3次.+1个或更多数字
  • _-文字_
  • (d+(?:.d+)+)-1个或多个数字,后面出现1个或更多.+1个或多数字
  • _-文字_
  • (d+)-最后一个或多个数字