std :: regex:匹配由数字和空格组成的字符串,并提取数字。怎么样?

时间:2020-06-14 09:45:47

标签: c++ regex

我想同时做两件事:将字符串与模式匹配并提取组。

字符串由空格和数字组成。我想将字符串与此模式匹配。另外,我想使用std :: smatch提取数字(不是数字,仅是一位数字)。

我尝试了很多,但没有成功。

对于骗子猎人:我在SO上检查了很多答案,但找不到解决方法。

然后,我尝试使用std::sregex_token_iterator。结果也让我感到困惑。在

#include <string>
#include <regex>
#include <vector>
#include <iterator>

const std::regex re1{ R"(((?:\s*)|(\d))+)" };

const std::regex re2{ R"(\s*(\d)\s*)" };

int main() {
    std::string test("   123 45 6   ");
    std::smatch sm;

    bool valid1 = std::regex_match(test, sm, re1);
    std::vector<std::string> v(std::sregex_token_iterator(test.begin(), test.end(), re2), {});
    return 0;
}

向量不仅包含数字,还包含空格。我只想输入数字。

smatch不包含任何数字。

我知道,我可以先从字符串中删除所有空格,但是应该有一个更好的一步解决方案。


正确的正则表达式是什么:1.将字符串与我描述的模式匹配,然后2.将所有单个数字提取到smatch中?

1 个答案:

答案 0 :(得分:2)

您需要验证的模式是

\s*(?:\d\s*)*

请参见regex demo(请注意,我添加了^$以使该模式与正则表达式测试站点上的整个字符串匹配,因为您在命令行中使用了等效的regex_match代码,则需要完整的字符串匹配。)

接下来,在使用第一个正则表达式验证了您的字符串后,您只需提取任意一位数字即可:

const std::regex re2{ R"(\d)" };
// ...
std::vector<std::string> v(std::sregex_token_iterator(test.begin(), test.end(), re2), {});

完整working snippet

#include <string>
#include <regex>
#include <vector>
#include <iterator>
#include <iostream>

const std::regex re1{ R"(\s*(?:\d\s*)*)" };

const std::regex re2{ R"(\d)" };

int main() {
    std::string test("   123 45 6   ");
    std::smatch sm;

    bool valid1 = std::regex_match(test, sm, re1);
    std::vector<std::string> v(std::sregex_token_iterator(test.begin(), test.end(), re2), {});
    for (auto i: v)
        std::cout << i << std::endl;

    return 0;
}

输出:

1
2
3
4
5
6

使用Boost的替代解决方案

仅当整个字符串由空格和数字组成时,才可以使用正则表达式来单独匹配所有数字

\G\s*(\d)(?=[\s\d]*$)

请参见regex demo

详细信息

  • \G-字符串的开始或之前成功匹配的结束
  • \s*-超过0个空格
  • (\d)-第1组中捕获的数字(当将1作为boost::sregex_token_iterator iter(test.begin(), test.end(), re2, 1)中的最后一个参数传递时,我们将仅返回该值)
  • (?=[\s\d]*$)-必须有0个或多个空格或数字,然后是当前位置右边的字符串结尾。

请参见whole C++ snippet(与-lboost_regex选项一起编译):

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

int main()
{
    std::string test("   123 45 6   ");
    boost::regex re2(R"(\G\s*(\d)(?=[\s\d]*$))");
    boost::sregex_token_iterator iter(test.begin(), test.end(), re2, 1);
    boost::sregex_token_iterator end;
    std::vector<std::string> v(iter, end);
    for (auto i: v)
        std::cout << i << std::endl;

    return 0;
}
相关问题