在JS正则表达式中,符号^
和$
分别表示字符串的开头和结尾。只有使用/m
修饰符(多行模式)时,它们才匹配每行的开头和结尾 - 即CR/LF之前和之后的位置。
但是,在std::regex/ECMAscript模式下,符号^
和$
总是匹配每行的开头和结尾。
在std::regex中是否有任何方法来定义字符串的开头和结尾的匹配点?换句话说,是否支持JavaScript的多行模式...
TL;DR
^
和 $
已经匹配了行的开头和结尾std::regex_constants::multiline
选项^
匹配字符串开头,$
匹配字符串结尾,并且无法重新定义它们的行为。std::regex
实现中,^
和$
匹配字符串的开头和结尾,而不是一行。参见this demo,它使用^\d+$
正则表达式无法在"1\n2\n3"
中找到任何匹配项。当您添加替代方案时(请参见下文),有3个匹配项。^
和$
可能与行的开头和结尾匹配。
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';
}
将输出
Match value: 1 at Position 0
Match value: 2 at Position 2
Match value: 3 at Position 4
适用于所有C++编译器的解决方案
std::regex
中没有一种通用选项,可以使锚点在所有编译器中匹配行的开头/结尾。您需要使用替代方法来模拟它:
^ -> (^|\n)
$ -> (?=\n|$)
$
可以通过 (?=\n|$)
(您可以添加更多行终止符号或符号序列,例如 (?=\r?\n|\r|$)
)来完全“模拟”,但是使用 ^
,您无法找到100%的解决方法。(^|\n)
,例如更经常地使用捕获组。^
视为输入开头和行首,并将$
视为输入结尾和行尾。无法使它们仅匹配输入开头或结尾,但可以使它们仅匹配行首或行尾:std::regex_match
、std::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
来暗示输入的开头。这在ECMAScript语法文档上很好地解释了,在cppreference.com上,我通常比cplusplus.com更加推荐。
警告:我已经测试了MSVC、Clang + libc++和Clang + libstdc++,目前只有MSVC具有正确的行为。
^
只匹配“输入的开头”,而不是其他任何内容。 - c-smilematch_not_eol
应该意味着完全相反的事情:如果设置了该标志,则不应匹配EOL,只能匹配输入的结尾,对吧?这确实有意义。按照您的解释,该标志是无用的。 - c-smilefirst
视为BOL或将last
视为EOL”,这不是你想要的。我提供文档链接是有原因的。;-] - ildjarn^
仅匹配输入的开头(与$
和输入的结尾相同)?在boost中,有明确的\A
和\z
标记,可以显式地匹配输入的头部/尾部:http://www.boost.org/doc/libs/1_31_0/libs/regex/doc/syntax.html 看起来std失去了这个功能。 - c-smilefirst
和last
是传递给正则表达式算法(搜索、匹配、替换)的迭代器范围。我认为std::regex
不支持您想要的ECMAScript语法,但POSIX语法可能有您想要的内容。我对这些并不是全面了解,但cppreference.com上有它们的语法链接。 - ildjarnstring reg = "^[a-z]+\\.*[a-z]*@gmail\\.com$";
regex reg1(reg, regex_constants::icase);
reg1(regex_str, regex_constants::icase);
string email;
cin>>email;
if (regex_search(email, reg1))
您可以使用JavaScript正则表达式^(?<!(.|\n)])
来模拟Perl/Python/PCRE的\A
,它在字符串开头匹配但不匹配换行符之后的字符。这个正则表达式的意思是“匹配没有前导字符的行的开头”。
您可以使用(?!(.|\n))$
来模拟Perl/Python/PCRE的\z
,它仅匹配字符串结尾。为了实现\Z
的效果,即仅在字符串结尾处允许单个换行符,只需添加一个可选的换行符:\n?(?!(.|\n))$
。
^
和$
匹配字符串的开头和结尾。请参见 https://ideone.com/amatBf 和 https://ideone.com/0D7eS7。 - Wiktor Stribiżew^
和$
? - c-smile(?=\n|$)
,对于行首,它只能是像(^|\n)
这样的消耗模式。我知道这非常不舒服。如果你真的需要^
/$
的多行行为,转换到 Boost 正则表达式可能是最好的选择。 - Wiktor Stribiżew