我想同时做两件事:将字符串与模式匹配并提取组。
字符串由空格和数字组成。我想将字符串与此模式匹配。另外,我想使用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中?
答案 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), {});
#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;
}