28

我想在另外两个之间提取一个子字符串。
例如:/home/toto/FILE_mysymbol_EVENT.DAT
或者只是FILE_othersymbol_EVENT.DAT
我想得到:mysymbolothersymbol

我不想使用 boost 或其他库。只是来自 C++ 的标准东西,除了 CERN 的 ROOT 库,带有TRegexp,但我不知道如何使用它......

4

4 回答 4

51

自去年以来,C++ 已经在标准中内置了正则表达式。该程序将展示如何使用它们来提取您所追求的字符串:

#include <regex>
#include <iostream>

int main()
{
    const std::string s = "/home/toto/FILE_mysymbol_EVENT.DAT";
    std::regex rgx(".*FILE_(\\w+)_EVENT\\.DAT.*");
    std::smatch match;

    if (std::regex_search(s.begin(), s.end(), match, rgx))
        std::cout << "match: " << match[1] << '\n';
}

它将输出:

匹配:mysymbol

但应该注意的是,它在 GCC 中不起作用,因为它的库对正则表达式的支持不是很好。在 VS2010(可能还有 VS2012)中运行良好,并且应该在 clang 中运行。


到现在(2016 年末),所有现代 C++ 编译器及其标准库都完全符合 C++11 标准,即使不是全部也是 C++14 标准。GCC 6 和即将到来的 Clang 4 也支持大部分即将到来的 C++17 标准。

于 2012-07-24T11:21:13.920 回答
3

与其他正则表达式相比,TRegexp 仅支持非常有限的正则表达式子集。这使得构建适合您需求的单个正则表达式有些尴尬。

一种可能的解决方案:

[^_]*_([^_]*)_

将匹配字符串直到第一个下划线,然后捕获所有字符直到下一个下划线。然后在第 1 组中找到匹配的相关结果。

但在你的情况下,为什么要使用正则表达式呢?只需_在字符串中找到第一次和第二次出现的分隔符,然后提取这些位置之间的字符。

于 2012-07-24T09:04:02.390 回答
3

如果你想使用正则表达式,我真的推荐使用 C++11 的正则表达式,或者,如果你有一个还不支持它们的编译器,Boost。Boost 是我认为几乎是标准 C++ 的一部分。

但是对于这个特定的问题,您实际上并不需要任何形式的正则表达式。beg != npos在添加所有适当的错误检查(等end != npos)、测试代码并删除我的拼写错误之后,像这个草图这样的东西应该可以正常工作:

std::string between(std::string const &in,
                    std::string const &before, std::string const &after) {
  size_type beg = in.find(before);
  beg += before.size();
  size_type end = in.find(after, beg);
  return in.substr(beg, end-beg);
}

显然,您可以将 更改std::string为模板参数,并且它应该可以很好地与std::wstring或更少使用的实例化一起使用std::basic_string

于 2012-07-24T09:25:56.047 回答
0

在信任它之前,我会研究极端案例。

但这是一个很好的候选人:

std::string text = "/home/toto/FILE_mysymbol_EVENT.DAT";
std::regex reg("(.*)(FILE_)(.*)(_EVENT.DAT)(.*)");
std::cout << std::regex_replace(text, reg, "$3") << '\n';
于 2020-02-14T21:15:54.510 回答