c ++ 11正则表达式提取文本

时间:2015-06-19 00:30:09

标签: c++ regex

我一直在尝试一些看似相当简单的事情......起初。

我正在尝试使用正则表达式转换我一直在使用strstr进行的文本操作,这似乎是现在使用c ++ 11的方法。这是一个测试案例:

<!Sometag>
// Lots of code here! (Multiline)
<Sometag!>

<!Sometag2>
// Lots of code here! (Multiline)
<Sometag2!>

编辑:一个更明确的例子。

/// Comments.

<!Vertex>
#version 150
/// code here!
void main()
{
 /// code here!
}
<Vertex!>

/// Comments.
<!Fragment>
#version 150
/// code here!

void main()
{
/// code here!
}
<Fragment!>

编辑2:这是一个需要工作的更好的例子:

regex editor

我已经做了很多组合,但最让人想到的是这一个:

std::smatch u;
std::string s = shader->GetData();
std::regex_match(s, u, std::regex("<.*>(.*)<!.*>"));

我还没有运气,我想知道是否有人会对语法可能有什么想法?!

THX

2 个答案:

答案 0 :(得分:0)

如果您的代码很整洁,可以尝试这样的代码:,

需要相应地转义为C,当然:(?:<[^<>!]*?>\n?)((.|\n)*?)(?:<!.*>(\n|$)?)

代码本身就是捕获组$ 1

https://regex101.com/r/vC5xD3/2(这是php,但想法仍然存在)。

答案 1 :(得分:0)

请考虑使用regex_search。然后,您可以访问每个子匹配。以下是您可以从...开始的示例...

std::smatch u;
std::string s = "<Sometag>\n// Lots of code here! (Multiline)\n<!Sometag>\n\n<Sometag2>\n// Lots of code here! (Multiline)\n<!Sometag2>\n";
std::regex e("<[^>]*>([^<]*)<[!][^>]*>[^<]*");
std::cmatch m;

while (s.length() > 0)
{
    bool result = std::regex_search(s.cbegin(), s.cend(), u, e);
    if (result == false)
        break;
    for (std::smatch::iterator it = u.begin(); it != u.end(); ++it)
    {
        std::cout << *it << std::endl;
    }
    s = u.suffix();
}

修改的 以下表达式更能容忍&lt;在代码中。

std::regex e("^<([^>]*)>(((.|\\n)*)<[!]\\1>[^<]*)?");

这种方式有更多的子匹配,但其中一个是标签之间的内容。

编辑2 根据您提供的更好的示例字符串,这是另一个将目标字符串分解为子匹配的代码示例。第四个子匹配是标签的实际内容

std::smatch u;
std::string s = "/// Comments.\r\n\r\n<!Vertex>\r\n#version 150\r\n\r\n//#define DISPLAY_DIFFUSE 0\r\n//#define DISPLAY_BUMP 1\r\n//#define DISPLAY_SPECULAR 2\r\n//#define ... \r\n\r\n<Vertex!>\r\n\r\n/// Comments.\r\n\r\n<!Fragment>\r\n#version 150\r\n\r\n//#define DISPLAY_DIFFUSE 0\r\n//#define DISPLAY_BUMP 1\r\n//#define DISPLAY_SPECULAR 2\r\n//#define ... \r\n\r\n<Fragment!>\r\n\r\n";
std::regex e("<[!]([^>]*)>");  //to skip to the first tag
std::cmatch m;

// search to the first tag
bool result = std::regex_search(s.cbegin(), s.cend(), u, e);
if (result == true)
{   // skip characters before first tag
    s = s.substr(u.prefix().length());

    // regex to find <!tag>...<tag!>... capturing several things
    // fourth sub-string is the content between the tags
    e = std::regex("^<[!]([^>]*)>(((.|[\\n\\r])*)<\\1[!]>[^<]*)");
    while (s.length() > 0)
    {
        // find a tag and its contents
        result = std::regex_search(s.cbegin(), s.cend(), u, e);
        if (result == false)
            break;
        // interate through the sub-matches (the 4th is the
        // contents between tags
        int idx = 0;
        for (std::smatch::iterator it = u.begin(); it != u.end(); ++it)
        {
            if(++idx == 4)
                std::cout << *it << std::endl;
        }
        s = u.suffix();
    }
}