GRETA正则表达式模板类库
副标题#e#
本文摘要翻译了几篇文章的内容,简朴先容 ATL CAtlRegExp,GRETA, Boost::regex 等正则表达式库,这些表达式库使我们可以利便地操作正则库的 庞大威力,给我们的事情提供了便利。
正则表达式语法
字符元 | 意义 |
. | 匹配单个字符 |
[ ] | 指定一个字符类,匹配方括号内的任意字符。例:[abc] 匹配 "a", "b"或 "c"。 |
^ | 假如^呈此刻字符类的开始处,它否认了字符类,这个被否认 的字符类匹配除却方括号内的字符的字符。如:[^abc]匹配除了"a", "b"和"c"之外的字符。假如^呈此刻正则表达式前边,它 匹配输入的开头,例:^[abc]匹配以"a", "b"或 "c"开头的输入。 |
– | 在字符类中,指定一个字符的范畴。譬喻:[0-9]匹配 "0"到"9"的数字。 |
? | 指明?前的表达式是可选的,它可以匹配一次或不举办匹配。 譬喻: [0-9][0-9]? 匹配"2"或"12"。 |
+ | 指明?前的表达式匹配一次或多次。譬喻:[0-9]+匹配 "1", "13", "666"等。 |
* | 指明*前的表达式匹配零次或多次。 |
??, +?, *? | ?, +和*的非贪婪匹配版本,它们尽大概匹配较少的字符; 而?, +和*则是贪婪版本,尽大概匹配较多的字符。譬喻:输入 "<abc><def>", 则<.*?> 匹配 "<abc>",而<.*>匹配 "<abc><def>"。 |
( ) | 分组操纵符。譬喻:(\d+,)*\d+匹配一串由逗号分隔的数字,譬喻: "1"或"1,23,456"。 |
\ | 转义字符,转义紧跟的字符。譬喻,[0-9]+ 匹配一个或多个数字,而 [0-9]\+ 匹配一个数字后跟从一个加号的环境。反斜杠\也用于暗示缩写,\a 就暗示任何数字、字母。假如\后紧跟一个数字n,则它匹配第n个匹配群组(从0开始),譬喻,<{.*?}>.*?</\0>匹配"<head>Contents</head>"。留意,在C++字符串中,反斜杠\需要用双反斜杠\\来暗示: "\\+", "\\a", "<{.*?}>.*?</\\0>"。 |
$ | 放在正则表达式的最后,它匹配输入的结尾。譬喻:[0-9]$匹 配输入的最后一个数字。 |
| | 隔断符,脱离两个表达式,以正确匹配个中一个,譬喻: T|the匹配"The" 或"the"。 |
缩写匹配
缩写 | 匹配 |
\a | 字母、数字([a-zA-Z0-9]) |
\b | 空格(blank): ([ \\t]) |
\c | 字母([a-zA-Z]) |
\d | 十进制数 ([0-9]) |
\h | 十六进制数([0-9a-fA-F]) |
\n | 换行: (\r|(\r?\n)) |
\q | 引用字符串(\"[^\"]*\")|(\””[^\””]*\””) |
\w | 一段文字 ([a-zA-Z]+) |
\z | 一个整数([0-9]+) |
#p#副标题#e#
ATL CATLRegExp
ATL Server经常需要对地点、呼吁等巨大文字字段信息解码,而正则表达式 是强大的文字理会东西,所以,ATL提供了正则表达式表明东西。
示例:
#include "stdafx.h"
输出:
#include <atlrx.h>
int main(int argc, char* argv[])
{
CAtlRegExp<> reUrl;
// five match groups: scheme, authority, path, query, fragment
REParseError status = reUrl.Parse(
"({[^:/?#]+}:)?(//{[^/?#]*})?{[^?#]*}(?{[^#]*})?(#{.*})? " );
if (REPARSE_ERROR_OK != status)
{
// Unexpected error.
return 0;
}
CAtlREMatchContext<> mcUrl;
if (!reUrl.Match(
"http://search.microsoft.com/us/Search.asp? qu=atl&boolean=ALL#results",
&mcUrl))
{
// Unexpected error.
return 0;
}
for (UINT nGroupIndex = 0; nGroupIndex < mcUrl.m_uNumGroups;
++nGroupIndex)
{
const CAtlREMatchContext<>::RECHAR* szStart = 0;
const CAtlREMatchContext<>::RECHAR* szEnd = 0;
mcUrl.GetMatch(nGroupIndex, &szStart, &szEnd);
ptrdiff_t nLength = szEnd - szStart;
printf("%d: \"%.*s\"\n", nGroupIndex, nLength, szStart);
}
}
0: "http"
1: "search.microsoft.com"
2: "/us/Search.asp"
3: "qu=atl&boolean=ALL"
4: "results"
#p#分页标题#e#
Match的功效通过第二个参数pContext所指向的CAtlREMatchContext类来返回 ,Match的功效及其相关信息都被存放在CAtlREMatchContext类中,只要会见 CAtlREMatchContext的要领和成员就可以获得匹配的功效。CAtlREMatchContext 通过m_uNumGroups成员以及GetMatch()要领向挪用者提供匹配的功效信息。 m_uNumGroups代表匹配上的Group有几多组,GetMatch()则按照通报给它的Group 的Index值,返回匹配上的字符串的pStart和pEnd指针,挪用者有了这两个指针 ,自然可以很利便的获得匹配功效。
更多内容请参阅: CAtlRegExp Class
GRETA
GRETA是微软研究院推出的一个正则表达式模板类库,GRETA 包括的 C++ 对 象和函数,使字符串的模式匹配和替换变得很容易,它们是:
" rpattern: 搜索的模式 " match_results/subst_results: 安排匹配、替换功效的容器
为了执行搜索和替换的操纵,用户首先需要用一个描写匹配法则的字符 串来显式初始化一个rpattern工具,然后把需要匹配的字符串作为参数,挪用 rpattern的函数,好比match()可能substitute(),就可以获得匹配后的功效。 假如match()/substitute()挪用失败,函数返回false,假如挪用乐成,函数返 回true,此时,match_results工具存储了匹配功效。请看例子代码:
#include <iostream>
#include <string>
#include "regexpr2.h"
using namespace std;
using namespace regex;
int main() {
match_results results;
string str( "The book cost $12.34" );
rpattern pat( "\\$(\\d+)(\\.(\\d\\d))?" );
// Match a dollar sign followed by one or more digits,
// optionally followed by a period and two more digits.
// The double-escapes are necessary to satisfy the compiler.
match_results::backref_type br = pat.match( str, results );
if( br.matched ) {
cout << "match success!" << endl;
cout << "price: " << br << endl;
} else {
cout << "match failed!" << endl;
}
return 0;
}
措施输出将是:
match success!
price: $12.34
您可以阅读GRETA文档,获知rpattern工具的细节内容,并把握如何自定 义搜索计策来获得更好的效率。
留意:所有在头文件regexpr2.h里的声明都在名称空间regex之中,用户 利用个中的工具和函数时,必需加上前缀"regex::",可能预先 "using namespace regex;" 一下,为了简朴起见,下文的示例代码 中将省略"regex::" 前缀。 作者生成了greta.lib和regexpr2.h文件 ,只需这两个文件的支持即可利用greta来理会正则表达式。
匹配速度小议
差异的正则表达式匹配引擎擅长于差异匹配模式。作为一个基准,当用 模式:"^([0-9]+)(\-| |$)(.*)$"匹配字符串"100- this is a line of ftp response which contains a message string"时,GRETA的 匹配速度比boost(http://www.boost.org)正则表达式库约莫快7倍,比ATL7的 CATLRegExp快10倍之多! Boost Regex 的说明文档带有一个许多模式的匹配测试 Performance功效。较量这个功效后,我发明GRETA在大部门环境下和Boost Regex机能差不多,可是在用Visual Studio.Net 2003编译的环境下,GRETA还略 胜一筹。
Boost.Regex
Boost提供了boost::basic_regex来支持正则表达式。 boost::basic_regex的设计很是雷同std::basic_string:
#p#分页标题#e#
namespace boost{
template <class charT,
class traits = regex_traits<charT>,
class Allocator = std::allocator<charT> > class basic_regex;
typedef basic_regex<char> regex;
typedef basic_regex<wchar_t> wregex;
}
Boost Regex 库附带的文档很是富厚,示例更是出色,好比有 两个例子措施,不多的代码,措施就可以直接对 C++ 文件举办语法高亮标志, 生成相应的 HTML (converts a C++ file to syntax highlighted HTML)。下面 的例子可以支解一个字符串到一串标志标记(split a string into tokens)。
#include <list>
#include <boost/regex.hpp>
unsigned tokenise(std::list<std::string>& l, std::string& s)
{
return boost::regex_split(std::back_inserter(l), s);
}
#include <iostream>
using namespace std;
#if defined(BOOST_MSVC) || (defined(__BORLANDC__) && (__BORLANDC__ == 0x550))
// problem with std::getline under MSVC6sp3
istream& getline(istream& is, std::string& s)
{
s.erase();
char c = is.get();
while(c != ''''\n'''')
{
s.append(1, c);
c = is.get();
}
return is;
}
#endif
int main(int argc)
{
string s;
list<string> l;
do{
if(argc == 1)
{
cout << "Enter text to split (or \"quit\" to exit): ";
getline(cin, s);
if(s == "quit") break;
}
else
s = "This is a string of tokens";
unsigned result = tokenise(l, s);
cout << result << " tokens found" << endl;
cout << "The remaining text is: \"" << s << "\"" << endl;
while(l.size())
{
s = *(l.begin());
l.pop_front();
cout << s << endl;
}
}while(argc == 1);
return 0;
}