std::regex::multiline不存在。

3

我尝试使用多行正则表达式语法,使得^$在C++中匹配行的开头和结尾。自C++17以来,std::regexstd::regex_constants应该包含一个标志multiline,可将其打开(请参考此处)。

我在苹果Clang、Ubuntu和Alpine上尝试了这个方法,但都没有成功,显示符号丢失。我做错了什么?我是否误解了自C++17以来的标准?

#include <regex>
int main() {
  auto flag = std::regex::multiline;
}

$ g++ --version
g++ (Ubuntu 9.2.1-9ubuntu2) 9.2.1 20191008
$ g++ regex.cpp -std=c++17 -o regex
regex.cpp: In function 'int main()':
regex.cpp:3:27: error: 'multiline' is not a member of 'std::__cxx11::regex' {aka 'std::__cxx11::basic_regex<char>'}
    3 |   auto flag = std::regex::multiline;
      |                           ^~~~~~~~~

1
std::regex_constants::syntax_option_type::multilinestd::regex_constants::multiline - KamilCuk
std::regex::multiline 应该可以工作,因为标志常量应该也在 std::basic_regex 类中声明。所以这可能是编译器实现中的一个错误。 - Remy Lebeau
@KamilCuk:我尝试了两种方法,结果一样。 - paulgessinger
@RemyLebeau:我尝试了GCC9和(Apple)Clang,但都无法工作。 - paulgessinger
@ephimetheus 那显然这些实现还没有达到标准规定的应该实现的水平。 - Remy Lebeau
3个回答

3

1

std::regex有一些很大的限制。我找到的唯一好的解决方案是使用boost::regex,然后你就可以轻松地实现多行匹配,而且好处在于它的语法完全相同,你只需要将所有的std::替换为boost::。哦,还有,它运行速度也快了20倍。

在这里查看比较表:https://www.regular-expressions.info/boost.html


仅说要使用不同的库并不能完全回答问题。问题在于,两年前的这个问题是因为它是一个旧的编译器,尚未实现该功能。 - ChrisMM
即使到今天,它仍未被实现。因此它非常相关。使用std::regex无法使其工作。 - Octo Poulos
它被g++支持,而OP正在使用它。 - ChrisMM
我可以确认std::regex::multiline现在在gcc12中存在,但在clang14中仍然似乎不存在。 - paulgessinger
@paulgessinger 不,它在clang14中存在,甚至在clang13中也存在(但需要使用c++17标准)。 - Michael
显示剩余3条评论

1

我也遇到了这个问题,在我的电脑上仍在使用clang-14 + gcc-11,并找到了这个解决方法:

^ 几乎可以被 (?:^|\n) 替换,$ 同样可以被 (?:$|\n) 替换(需要注意消耗 \n 字符)。

如果例如 $ 替换匹配到行末,那么 ^ 替换将不会在下一行匹配,因为 \n 已经消失。因此,在下面的示例中,我将两个规则拆分为两个单独的正则表达式规则,并分别搜索它们。

示例:

#include <iostream>
#include <regex>

//multi-line input string
const std::string t = "abc1 xyz2 abc3\nxyz4 abc5 xyz6\nabc7 xyz8 xyz9";
// search "^abc#" and "xyz#$" over multiple lines of input
// `^` is replaced with non-capture group `(?:^|\n)`, `$` with `(?:$|\n)`:
const auto e_bol = std::regex(R"((?:^|\n)(abc\d))");
const auto e_eol = std::regex(R"((xyz\d)(?:$|\n))");

int main() {
    std::cout << "input:\n" << t << std::endl;
    auto it_e = std::sregex_iterator();
    auto it_bol = std::sregex_iterator(t.cbegin(), t.cend(), e_bol);
    auto it_eol = std::sregex_iterator(t.cbegin(), t.cend(), e_eol);
    std::cout << "\n\"^abc\\d\" search:";
    for (;it_bol != it_e; ++it_bol) std::cout << ' ' << it_bol->str(1);
    std::cout << "\n\"xyz\\d$\" search:";
    for (;it_eol != it_e; ++it_eol) std::cout << ' ' << it_eol->str(1);
    std::cout << std::endl;
}

输出:

input:
abc1 xyz2 abc3
xyz4 abc5 xyz6
abc7 xyz8 xyz9

"^abc\d" search: abc1 abc7
"xyz\d$" search: xyz6 xyz9

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