写在前面
个人对于正则表达式实在是不太了解,所以本文内容纰漏应该会比较多。只希望不会对大家造成误导。
本文只是简单涉及C++0x、Qt4、Python3、Vim中的正则表达式:
-
C++0x :在 regexp 头文件中提供一系列模板类
-
Qt4 :中提供了 QRegExp 类
-
Python3 :中提供了 re 模块
-
Vim :命令模式和脚本支持正则
晕,写了一上午,竟然写成了这样了,Vim竟然都没涉及,其他部分也是一团糟,额,本来是想整理它们之间的在pattern上的区别的。不管了,先这样吧。
2011.08.20
用途
两个问题+三个动作?(真不知道该如何分类了...):
-
match: 字符串匹配这个模式(pattern)么?
-
search: 字符串中存在和模式匹配的字串么?
-
capture: 捕获匹配的字符串
-
replace: 替换字符串(子串)
-
split: 分割字符串
使用
准备pattern字符串
这个?元字符、匹配单个字符、重复匹配等,似乎相关的资料太多了哈,这儿暂时省略。
Python提供raw字符串的字面量写法,C++0x也提供了这种功能,只是编译器目前似乎都尚不支持。
//C++0x const char * str1 = "C://windows//system32"; const char * str2 = R"(C/windows/system32)";
生成pattern对象
Python | re.compile(pattern, flags=0)生成对象 |
Qt | 使用QRegExp构造函数,可通过QRegExp::setPattern()修改 |
C++0x | 通过模板类basic_regex构造 |
Python 下面,通过 re.compile() 可以生成一个正则表达式对象(Regular Expression Objects)
>>> import re >>> re.compile(r"dbzhang8\d{2}") <_sre.SRE_Pattern object at 0xb731c720> >>>
-
如果稍后只是使用re模块级的函数,比如re.match(r"dbzhang8\d{2}", "dbzhang800"),那么不必先使用compile生成正则表达式对象。
C++0x 和 Qt 下,直接使用构造函数生成对象
QRegExp qt_pattern("dbzhang8\\d{2}"); std::regex cpp_pattern("dbzhang8\\d{2}");
-
在C++0x中,有char,wchar_t,char16_t,char32_t 这4种字符类型,std::regex 只是一个别名 typedef basic_regex<char> regex;
执行匹配操作
看看Python
match() | 判断RE是否从字符串“开头”开始匹配 | 成功则返回一个MatchObject对象,否则返回None | 这4个函数均有模块级 和 对象的成员函数两种形式。区别在于后者需要先编译一个正则表达式对象,该对象可以重复使用。 |
search() | 扫描字符串,看是否有匹配的字串 | ||
findall() | 查找所有匹配的字串,将它们作为一个list返回 | ||
finditer() | 查找所有匹配的字串,将它们以迭代器(iterator)返回 |
- 简单的例子:
>>> p = re.compile(r"dbzhang8\d{2}") >>> print(p.match("dbzhang-800")) None >>> p.match("dbzhang801") <_sre.SRE_Match object at 0xb71d3fa8> >>> p.findall("dbzhang801dbzhang802") ['dbzhang801', 'dbzhang802']
注意:MatchObject包含匹配信息,可以用来提取匹配的字符串
看看Qt
QRegExp::exactMatch() | 判断字符串是否完全(从头到尾)匹配,返回真或假 | 这3个操作都会设置 matchedLength()、capturedTexts()、pos()的信息,类似于前面python中的MatchObject |
QRegExp::indexIn() | 搜索字符串以找到匹配的字串,返回索引值,失败返回-1 | |
QRegExp::lastIndexIn() | 同上,只是从后向前搜索 | |
QString::indexOf() | 如果只是查找的话,这两个更方便,只是无法获取额外的capturedTexts等信息了 | |
QString::contains() | 是否匹配 | |
QString::count() | 多少次匹配 |
恩,看看C++0x
regex_match() | 表达式是否完整匹配一个字符串? | 返回值是布尔量,但执行时会填充一个match_results对象,以用来进行字串捕捉。注意:这些是算法,不是前面提到的basic_regex的成员函数。 |
regex_search() | 是否匹配字符串的一部分? |
看看Capture信息?
要Capture字串的话,正则的pattern需要使用圆括号“()”包住一部分。
前面看到,match、search、index、... 等操作,都会通过其他方式填充一些额外的信息
-
Python 中生成一个 MatchObject 对象
- C++ 0x 填充 match_result 对象
- Qt 通过QRegExp对象自身 matchedLength()、capturedTexts()、pos() 的成员函数
Python
group() | 返回匹配的字符串 | 需指定哪一个(或哪几个)组,默认是0组(匹配自身) |
start() | 返回匹配的起始位置 | |
end() | 返回匹配的结束位置 | |
span() | 返回包含起始和结束位置的元组(tuple) | |
groups() | 返回所有匹配的组 |
Qt 中:
matchedLength() | 匹配的长度 | |
captureCount() | 表达式中含有的捕捉组的数目 | |
capturedTexts() | 捕捉到的字符串列表 | |
pos(int n) | 第n个组的位置 | |
cap(int n) | 第n个组的内容(0代表匹配自身) |
C++0x 中:
match_results::operator[](size_type n) | 返回第n个捕捉组(0代表匹配自身) | 返回的是sub_match模板类的对象 |
match_results::prefix() | 返回被匹配子串前面的串 | |
match_results::suffix() | 返回被匹配子串后面的串 | |
match_results::empty() | 只在匹配失败是返回true | |
match_results::size() | 组的数目 | |
match_results::str() | 组的内容 | |
match_results::position() | 位置 |
- 4个别名:
typedef match_results<const char*> cmatch; typedef match_results<const wchar_t*> wcmatch; typedef match_results<string::const_iterator> smatch; typedef match_results<wstring::const_iterator> wsmatch;
执行修改操作
Python
split() | 分割字符串 | 可指定最大分割或替代的数目 |
sub() | 替换所有匹配的子串 | |
subn() | 同上,但同时返回多少次替换发生(返回的是元组) |
Qt中:
QString::split() | 全是QString的成员函数,简单明了 |
QString::section() | |
QString::replace() | |
QString::remove() |
C++0x中:
regex_replace() | 就这一个么?呵呵 |