环视说起来有些拗口,但看具体的例子就容易理解了:
#include <iostream> #include <regex> using namespace std; void isMatch(const char* content, const char* reg_ex) { cout << "Is '" << reg_ex << "' match '" << content << "': "; smatch match; string s(content); regex reg(reg_ex); if(regex_search(s, match, reg)) { cout << "YES" << endl; } else { cout << "NO" << endl; } } int main() { isMatch("sometimes", "(?=sometimes)some"); isMatch("something", "(?=sometimes)some"); cout << endl; isMatch("some eggs", "(?!some birds)some"); isMatch("some birds", "(?!some birds)some"); return 0; }这段代码并不复杂所以就不多做说明,它的输出结果如下:
Is 'sometimes' match '(?=sometimes)some': YES Is 'something' match '(?=sometimes)some': NO Is 'some eggs' match '(?!some birds)some': YES Is 'some birds' match '(?!some birds)some': NO对于包含环视的正则表达式来说,环视之外的内容是匹配的主体,环视本身只是一个附件条件。(?=sometimes)这个肯定顺序环视要求从这个位置开始,接下来的字符串必须是"sometimes"才能完成匹配。(?!some birds)这个否定顺序环视要是接下来的字符串一定不能是"some birds"才能完成匹配。
为了进一步帮助你理解,我们以图示的方式将(?=sometimes)some匹配"something"的过程描述出来。
图示中,虚线的上面是待匹配的文本,下面是正则表达式。对于环视,我们可以将其环视条件和主体分开来看。我们以一个下标三角箭头表示当前匹配的搜索位置。
刚开始的时候,搜索的位置是第一个字符的前面:
接下来,搜索位置往后走一个字符:
这个过程可以一直进行,直到匹配完"some":
虽然正则表达式的主体"some"完成了匹配,但是接下来环视的条件却无法满足,于是匹配失败:
但是,如果要匹配内容正好是"sometimes",则条件是满足的,于是就完成了匹配。
结束语因为是入门的文章,所以本文中所举例的正则表达式都很简单。但实际应用的时候,我们常常会写出非常复杂的正则表达式。你可以点击这里浏览一些示例:Regular Expression Library。
复杂的正则表达式常常很难理解,你可能需要借助工具来帮助分析,下面两个工具也许能帮上忙:
https://regex101.com
https://www.debuggex.com
想要很好的掌握正则表达式,多使用多练习是最好的方法。想要深入学习正则表达式,Jeffrey E.F. Friedl的《精通正则表达式》可能是最好的选择。
参考资料与推荐读物保罗的酒吧:Regex
Mastering Regular Expressions
Modified ECMAScript regular expression grammar
9. Regular Expressions - The Open Group Base Specifications Issue 7, 2018 edition
C++ Regular expressions library