C++正则表达式只能找到一个子匹配

6
// Example program
#include <iostream>
#include <string>
#include <regex>
int main()
{
 std::string strr("1.0.0.0029.443");

    std::regex rgx("([0-9])");
    std::smatch match;

    if (std::regex_search(strr, match, rgx)) {
        for(int i=0;i<match.size();i++)
            std::cout << match[i] << std::endl;
    }
}

这个程序应该写:

1
0
0
0
0
2
9
4
4
3

但是它会写入。
1
1

我在http://cpp.sh/和Visual Studio上都测试了一下,结果相同。
为什么只找到两个匹配项?并且它们为什么相同?
从这里的答案中我理解到,正则表达式搜索会在第一个匹配项处停止,并且匹配变量保存必要的(子?)字符串值以便继续(通过重复)查找其他匹配项。另外,由于它在第一个匹配项处停止,所以圆括号()只用于结果中的子匹配项。
2个回答

12

调用一次regex_search,它会将第一个匹配项存储在match变量中。在match中的集合包括匹配项本身和如果有的话捕获组。

为了获取所有匹配项,需要在循环中调用regex_search

while(regex_search(strr, match, rgx))
{
    std::cout << match[0] << std::endl;
    strr = match.suffix();
}
请注意,在您的情况下,第一个捕获组与整个匹配相同,因此不需要使用该组,您可以将正则表达式简单地定义为[0-9](不需要使用括号)。
演示:https://ideone.com/pQ6IsO

为什么它只将一个搜索匹配项放入匹配变量中?它在第一次匹配时停止搜索了吗? - huseyin tugrul buyukisik
\\d is a slightly shorter alternative to [0-9] - AndyG
感谢您提供这个重要信息。 - huseyin tugrul buyukisik
2
@huseyintugrulbuyukisik:我认为你误解了match变量的作用。它不是用于保存多个匹配项的,而是用于保存匹配项内的匹配子组(在括号中指定的组)。 - Benjamin Lindley
如果我想找到三个浮点变量,我需要循环3次,然后如果我理解正确的话。(当然要用适当的正则表达式代码) - huseyin tugrul buyukisik

1

问题:

  1. 仅使用if只能匹配一次。您需要使用while循环来查找所有匹配项,并在下一次循环中搜索上一个匹配项之后的文本。
  2. std::smatch::size()返回1 +匹配项数量。请参见其文档std::smatch可能包含子匹配项。要获取整个文本,请使用match[0]

这是您程序的更新版本:

#include <iostream>
#include <string>
#include <regex>

int main()
{
   std::string strr("1.0.0.0029.443");

   std::regex rgx("([0-9])");
   std::smatch match;

   while (std::regex_search(strr, match, rgx)) {
      std::cout << match[0] << std::endl;
      strr = match.suffix();
   }
}

我猜在C#中没有像string.Split(stringArray,..)一样的一行代码来获取所有部分。 - huseyin tugrul buyukisik
@huseyintugrulbuyukisik,我没有用过C#编程,无法回答这个问题。 - R Sahu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接