将 C# 正则表达式与 lookbehinds 翻译成 C++

Translate C# regex with lookbehinds to C++

@polygenelubricants 对 this question 的回答包括一个 C# 正则表达式,用于将 PascalCase 字符串拆分为单独的单词,即:

Regex r = new Regex(
   @"  (?<=[A-Z])(?=[A-Z][a-z])    # UC before me, UC lc after me
    |  (?<=[^A-Z])(?=[A-Z])        # Not UC before me, UC after me
    |  (?<=[A-Za-z])(?=[^A-Za-z])  # Letter before me, non letter after me
    ",
   RegexOptions.IgnorePatternWhitespace
);

我想在 C++ 中使用相同的正则表达式。但是,C++ 正则表达式语法不允许 (?<=...) 形式的回顾。无论如何都可以完成这项工作吗?

编辑:这显然不是重复的。我知道 C++ 不支持 lookbehinds,我想问如果没有它们是否可以实现相同的功能。作为参考,以下是使用 Boost 正则表达式执行此操作的方法,它确实支持后视并且我希望避免使用它:

#include <iostream>

#include <boost/algorithm/string/regex.hpp>
#include <boost/regex.hpp>

int main()
{

  boost::regex r(
    "(?<=[A-Z])(?=[A-Z][a-z])"
    "|(?<=[^A-Z])(?=[A-Z])"
    "|(?<=[A-Za-z])(?=[^A-Za-z])"
  );

  std::vector<std::string> input {
    "AutomaticTrackingSystem",
    "XMLEditor",
    "AnXMLAndXSLT2.0Tool"
  };

  for (auto const &str : input) {
    std::vector<std::string> str_split;

    boost::algorithm::split_regex(str_split, str, r);

    for (auto const &str_ : str_split)
      std::cout << str_ << std::endl;
  }
}

您可以将正则表达式更改为不使用回顾:[A-Z](?=[A-Z][a-z])|[^A-Z](?=[A-Z])|[A-Za-z](?=[^A-Za-z])

最后原来的正则表达式是在寻找新词的开头,所以它不得不在后面寻找前一个词的结尾。但是我们可以寻找一个词的结尾并向前看下一个词的开头。那么我们只需要将位置“移动”+1.

const std::sregex_iterator End;

// the code doesn't handle correctly "",
// handle as a special case
std::string str = "ThisIsAPascalStringX";

std::regex rx("[A-Z](?=[A-Z][a-z])|[^A-Z](?=[A-Z])|[A-Za-z](?=[^A-Za-z])");

std::vector<std::string> pieces;

size_t lastStartPosition = 0;

for (auto i(std::sregex_iterator(str.begin(), str.end(), rx)); i != End; ++i)
{
    size_t startPosition = i->position() + 1;

    pieces.push_back(str.substr(lastStartPosition, startPosition - lastStartPosition));
    lastStartPosition = startPosition;
}

pieces.push_back(str.substr(lastStartPosition));

std::cout << "<-- start" << std::endl;

for (auto& s : pieces)
{
    std::cout << s << std::endl;
}

std::cout << "<-- end" << std::endl;