std :: regex,匹配字符串的开头/结尾

c-s*_*ile 12 c++ regex std c++11

在JS正则表达式符号中^$指定字符串的开头和结尾.并且只有/m修改器(多线模式)才能匹配线的起点和终点 - 在CR/LF之前和之后的位置.

但在性病::正则表达式/EcmaScript的模式符号^$比赛的开始和行结束始终.

在std :: regex中有什么方法可以定义字符串匹配点的开始和结束吗?换句话说:支持JavaScript多线模式......

ild*_*arn 7

默认情况下,EcmaScript的模式已经把^既开始输入的,并且开始的行,并$为最终的输入都结束线.没有办法让它们匹配开头或结尾输入,但可以使它们匹配开头或结尾:

调用std::regex_matchstd::regex_search,或者std::regex_replace,有一个std::regex_constants::match_flag_type默认类型的参数std::regex_constants::match_default.

  • 要指定^仅匹配行首,请指定std::regex_constants::match_not_bol
  • 要指定$仅匹配行尾,请指定std::regex_constants::match_not_eol
  • 由于这些值是位标志,要指定两者,只需按位 - 或它们在一起(std::regex_constants::match_not_bol | std::regex_constants::match_not_eol)
  • 请注意,可以隐含输入开始而不使用^,无论是否存在std::regex_constants::match_not_bol指定std::regex_constants::match_continuous

这在cppreference.com上的ECMAScript语法文档中有很好的解释,我强烈推荐cplusplus.com.

警告:我已经使用MSVC,Clang + libc ++和Clang + libstdc ++进行了测试,目前只有MSVC具有正确的行为.

  • 来自您的链接 cppreference.com 断言 ^ (行开头)匹配 1) 紧跟在 LineTerminator 字符后面的位置。(如果支持,请参阅 LWG 问题 2343) 2) 输入的开头(除非启用 std::regex_constants::match_not_bol(C++ only)) 这与所需的完全不同。我需要“^”来匹配“输入的开头”,而不是其他任何东西。 (2认同)

Wik*_*żew 5

TL; DR

  • MSVC:^$已经匹配的行的开头和结尾
  • C ++ 17:使用 std::regex_constants::multiline选项
  • 其他编译器仅将string的开头^和结尾匹配$,无法重新定义其行为。

std::regex除MSVC之外且在C ++ 17之前的所有实现中,^and $匹配字符串的开头和结尾,而不是一行。请参见此演示该演示找不到"1\n2\n3"^\d+$regex 匹配的内容。当您添加交替(见下文)时,有3个匹配项

然而,在MSVC和C ++ 17中,^并且$可以匹配开始/所述的端线

C ++ 17

使用该std::regex_constants::multiline选项。

MSVC编译器

在Visual Studio中的一个C ++项目中,以下内容

std::regex r("^\\d+$");
std::string st("1\n2\n3");
for (std::sregex_iterator i = std::sregex_iterator(st.begin(), st.end(), r);
    i != std::sregex_iterator();
    ++i)
{
    std::smatch m = *i;
    std::cout << "Match value: " << m.str() << " at Position " << m.position() << '\n';
}
Run Code Online (Sandbox Code Playgroud)

将输出

Match value: 1 at Position 0
Match value: 2 at Position 2
Match value: 3 at Position 4
Run Code Online (Sandbox Code Playgroud)

跨C ++编译器的变通办法

没有通用选项std::regex可以使锚在所有编译器中都与行的开头/结尾匹配。您需要以交替方式模仿它:

^ -> (^|\n)
$ -> (?=\n|$)
Run Code Online (Sandbox Code Playgroud)

请注意,$可以使用完全“模拟” (?=\n|$)(您可以在其中添加更多的行终止符或符号序列,例如(?=\r?\n|\r|$)),但是使用^,则找不到100%的解决方法。

由于没有后向支持,因此您可能需要调整正则表达式模式的其他部分,因为(^|\n)比起向后支持,您更喜欢使用捕获组。

  • “断言^(行的开头)与紧接LineTerminator字符的位置相匹配。...” http://en.cppreference.com/w/cpp/regex/ecmascript (2认同)