使用regex.h进行全词匹配

Whole-word matching with regex.h

本文关键字:regex 使用      更新时间:2023-10-16

我想要一个C++正则表达式,它匹配"香蕉"或"睡衣",但不匹配"bananas2"、"bananas睡衣"或"香蕉",或者基本上除了这两个词之外的任何词。所以我做了这个:

#include <regex.h>
#include <stdio.h>
int main()
{
  regex_t rexp;
  int rv = regcomp(&rexp, "\bbananas\b|\bpajamas\b", REG_EXTENDED | REG_NOSUB);
  if (rv != 0) {
    printf("Abandon hope, all ye who enter heren");
  }
  regmatch_t match;
  int diditmatch = regexec(&rexp, "bananas", 1, &match, 0);
  printf("%d %dn", diditmatch, REG_NOMATCH);
}

并且它打印CCD_ 1,就好像没有匹配一样。发生了什么?我还为正则表达式尝试了bbananasb|bpajamasb,但也失败了。

我用regex询问了关于std::regex的全词匹配,但std::regx很糟糕,速度很慢,所以我正在尝试regex.h。

POSIX标准既没有为BRE和ERE指定单词边界语法,也没有为其指定look-behind-and-look-ahead语法(可用于模拟单词边界)。因此,不可能编写一个具有单词边界的regex,它可以在不同的POSIX兼容平台上工作

对于可移植的解决方案,如果您计划使用C++进行编码,则应该考虑使用PCRE或Boost.Regex。

否则,您将使用不可移植的解决方案。如果你可以接受这样的限制,有几个替代方案:

  • 如果你链接到GNU C库,它会扩展语法以包括单词边界,以及其他内容:b(单词边界)、B(非单词边界),<(单词的开头)、>(单词的结尾)
  • 一些系统将BRE和ERE语法扩展为包括[[:<:]](单词的开头)、[[:>:]](单词的结尾)语法

Konrad留下了一个很好的答案,解决了我的问题,但它不知怎么消失了,所以我无法接受。以下是为子孙后代打印正确内容的代码:

#include <regex.h>
#include <stdio.h>
int main()
{
  regex_t rexp;
  int rv = regcomp(&rexp, "[[:<:]]bananas[[:>:]]|[[:<:]]pajamas[[:>:]]", REG_EXTENDED | REG_NOSUB);
  if (rv != 0) {
    printf("Abandon hope, all ye who enter heren");
  }
  regmatch_t match;
  int diditmatch = regexec(&rexp, "bananas", 1, &match, 0);
  printf("%d %dn", diditmatch, REG_NOMATCH);
}

使用

s == "balances" || s == "pajamas"

而其中CCD_ 10是CCD_。

正则表达式可能会使简单的解决方案过于复杂。如果你想要固定的匹配,尤其要避免它们。