【问题标题】:Why does my Boost.Regex search report only one match iteration?为什么我的 Boost.Regex 搜索只报告一次匹配迭代?
【发布时间】:2010-10-12 18:01:43
【问题描述】:

我试图找出一个字符串中有多少个正则表达式匹配。我正在使用迭代器来迭代匹配,并使用整数来记录有多少。

long int before = GetTickCount();
string text;

boost::regex re("^(\\d{5})\\s(\\d{8})\\s(.*)\\s(.*)\\s(.*)\\s(\\d{8})\\s(.{1})$");
char * buffer;
long length;
long count;
ifstream f;


f.open("c:\\temp\\test.txt", ios::in | ios::ate);
length = f.tellg();
f.seekg(0, ios::beg);

buffer = new char[length];

f.read(buffer, length);
f.close();

text = buffer;
boost::sregex_token_iterator itr(text.begin(), text.end(), re, 0);
boost::sregex_token_iterator end;

count = 0;
for(; itr != end; ++itr)
{
    count++;
}

long int after = GetTickCount();
cout << "Found " << count << " matches in " << (after-before) << " ms." << endl;

在我的示例中,count 始终返回 1,即使我将代码放在 for 循环中以显示匹配项(并且有很多)。这是为什么?我做错了什么?

编辑

测试输入:

12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N

输出(不匹配):

在 16 毫秒内找到 1 个匹配项。

如果我将 for 循环更改为:

count = 0;
for(; itr != end; ++itr)
{
    string match(itr->first, itr->second);
    cout << match << endl;
    count++;
}

我得到这个作为输出:

12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
Found 1 matches in 47 ms.

【问题讨论】:

  • 我对 boost 了解不多,但是 end 没有初始化。这是故意的吗?
  • 是的。循环工作得很好。如果我输出匹配项,它们会显示出来,但计数仍然是 1。
  • 你找到多少匹配,可以计算滚动吗?
  • 尝试将 iter init 中的最后一个数字更改为 1 或 -1,请参阅我的帖子以获得解释。
  • +1 表示整件事是一场比赛。

标签: c++ regex iterator greedy boost-regex


【解决方案1】:

呵呵。你的问题是你的正则表达式。将您的 (.\*)s 更改为 (.\*?)s(假设支持)。您认为您看到每一行都被匹配,但实际上您看到的是匹配整个文本,因为您的模式是贪婪的。

要查看说明的问题,请将循环中的调试输出更改为:

cout << "[" << match << "]" << endl;

【讨论】:

    【解决方案2】:

    对 boost 了解不多,但是 (end - itr) 有用吗?

    【讨论】:

      【解决方案3】:

      由于您是说即使输出结果,计数仍然是 1,您可能需要查看几件事来帮助诊断:

      • 尝试在每次循环迭代中输出计数,看看会发生什么。如果这只输出一次,那么循环只运行一次,而你认为​​的多个匹配实际上是一个大的长匹配。
      • 如果可行,请尝试完全使用另一个变量名:在声明多个 count 变量时,可能会出现一些范围阴影。

      如果该循环多次执行,那么问题不在于您如何使用 boost。无论您在做什么,boost 都无法修改您未传递给它的变量。 (当然,如果您将 count 传递给某个地方进行提升,那么这是另一种可能性。)

      很可能,您拥有的第一个(.*) 将匹配所有内容,直到输入几乎结束(包括换行符)。尝试用([^ ]*) 替换那些(除了空格之外的任何内容,因此匹配在找到空格时停止。

      【讨论】:

      • 你是对的,但为什么会有'。'匹配换行符?文档说“除了换行符”
      • 它们可能不是您认为的换行符?也许他们只是\r\n 而boost 只处理\r\n?我对 boost::regex 的了解还不够多。虽然我似乎记得你必须在某处的构造函数中指定不匹配的换行符。
      【解决方案4】:

      你能粘贴输入和输出吗?

      如果 count 返回 1,这意味着您的字符串 text 中只有 一个 匹配项。

      【讨论】:

      • 是的,但就像我说过的,如果我将代码放入循环中以打印匹配项,则会打印多个且计数仍为 1。我还更改了sregex_token_iterator 为 -1,计数更改为 2。
      猜你喜欢
      • 1970-01-01
      • 2017-10-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多