GRETA正则表达式模板类库

王朝vc·作者佚名  2006-01-17
窄屏简体版  字體: |||超大  

GRETA正则表达式模板类库

编译:胡金山

下载源代码

本文摘要翻译了几篇文章的内容,简单介绍 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匹配"<headContents</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]+)

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"

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:

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;

}

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
 
© 2005- 王朝網路 版權所有 導航