<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>Regex on Shell&#39;s Home</title>
		<link>//blog.shell909090.org/tags/regex/</link>
		<description>Recent content in Regex on Shell&#39;s Home</description>
		<generator>Hugo</generator>
		<language>en-us</language>
		
		
		
			<copyright>CC-BY-SA4.0</copyright>
		
		
			<lastBuildDate>Thu, 21 Dec 2006 20:04:02 +0800</lastBuildDate>
		
			<atom:link href="//blog.shell909090.org/tags/regex/index.xml" rel="self" type="application/rss+xml" />
			<item>
				<title>正则表达式解析文本</title>
				<link>//blog.shell909090.org/blog/archives/339/</link>
				<pubDate>Thu, 21 Dec 2006 20:04:02 +0800</pubDate>
				<guid>//blog.shell909090.org/blog/archives/339/</guid>
				<description>&lt;p&gt;最近碰到这么个问题，一个文本，每行都是乱糟糟的东西，要从里面解析出东西来。行匹配铁定是用正则表达式，我用了Boost，不会的看我前两天的blog去。&lt;/p&gt;&#xA;&lt;p&gt;下面是按行解析问题。简单来说，写一个类继承Lister，然后实现里面的三个纯虚方法。maxSeqence返回最大可以支持的表达式，registe_regex返回表达式文本，seqenceProcess返回相应函数的指针。其实可以写成直接调用seqenceProcess加上匹配序号，然后让用户在函数内部做switch-case的。不过这样用户代码量稍微有点多，所以干脆玩一把技术。然后是几个非纯虚函数，nextSeqence可以根据当前状态来控制下一个要匹配的表达式，默认是+1，一个一个全部匹配。beforeProcess和afterProcess分别是处理前后，可以调整输入流。noMatch是一个比较常用的虚函数，用于响应没有匹配时的状态。&lt;/p&gt;&#xA;&lt;p&gt;匹配的结果在cmatch &amp;amp; what中，详细请看boost::regex。不过what[0].str()可以获得整句的string型返回，what[1]开始就是正则的匹配结果。&lt;/p&gt;&#xA;&lt;p&gt;&amp;mdash;&amp;mdash;&amp;mdash;2006-12-25&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&lt;/p&gt;&#xA;&lt;p&gt;原来的结果删除，我重写了一个。&lt;/p&gt;&#xA;&lt;p&gt;主要有两个问题，一个是getline的效率问题，我会撰文说明的。还有就是两处细节不大好。&lt;/p&gt;&#xA;&lt;p&gt;为了修正这两个问题，我突然发现整个的构架不大好了——怎么办？重写吧——&lt;/p&gt;&#xA;&lt;p&gt;下面是新的，一个类line_regex，直接继承就好。line_buffer是用于解决getline效率不高的问题的，当然我偷了个懒，实现代码用了WIN32API，所以是不可移植的。而且数据是一次读取，最多256M。不过相信这种级别的问题还难不倒大家。line_buffer类中的函数都很清晰明了，就不介绍了。&lt;/p&gt;&#xA;&lt;p&gt;Process (tistream &amp;amp; is)和Process (line_buffer &amp;amp; lb)是两大入口，同时支持自有的输入方法和流输入。当然流输入清晰明了标准化程度高。不过效率差的一塌糊涂。继承类初始化的时候，记得设置pfTable为入口列表，然后调用注册函数完成注册。nextSeqence和上面一样，可以定制下一个匹配式。noMatch用于无匹配的时候。beforeProcess和afterProcess分别会在某行开始和结束匹配后用，返回-1结束运行。其中beforeProcess返回正数会导致本行跳过，可以作为过滤器。&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;---------------------LineRegex.h--------------------&#xA;&#xA;#include&#xA;#include&#xA;#include&#xA;#include&#xA;#include&#xA;#include&#xA;#include&#xA;using namespace std;&#xA;using namespace boost;&#xA;&#xA;typedef basic_stringtstring;&#xA;typedef basic_regextregex;&#xA;typedef match_resultstmatch;&#xA;typedef basic_istream &amp;gt;tistream;&#xA;&#xA;#ifndef_LINE_REGEX_H_&#xA;#define_LINE_REGEX_H_&#xA;&#xA;class line_regex;&#xA;typedef int (line_regex::*ProcessFunction) (const tmatch &amp;amp; what,&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&#x9;int line);&#xA;&#xA;class line_buffer {&#xA;public:&#xA;&#x9;line_buffer();&#xA;&#x9;~line_buffer();&#xA;&#x9;intopen(LPCTSTR lpPath);&#xA;&#x9;voidclose();&#xA;&#x9;LPTSTRgetline();&#xA;&#x9;longsize();&#xA;protected:&#xA;&#x9;UINTFileSize;&#xA;&#x9;LPVOIDlpFile;&#xA;&#x9;TCHAR *lpNow, *lpNext;&#xA;};&#xA;&#xA;class line_regex {&#xA;public:&#xA;&#x9;line_regex();&#xA;&#x9;~line_regex();&#xA;&#x9;virtualintnextSeqence(int seqence);&#xA;&#x9;virtual intnoMatch(LPTSTR strLine, int line);&#xA;&#x9;virtual int beforeProcess (LPTSTR strLine, int line);&#xA;&#x9;virtual int afterProcess (LPTSTR strLine, int line);&#xA;&#x9;voidregiste_expression(LPCTSTRexps[]);&#xA;&#x9;int Process (tistream &amp;amp; is);&#xA;&#x9;int Process (line_buffer &amp;amp; lb);&#xA;protected:&#xA;&#x9;intProcessLine(LPTSTR strLine, int line);&#xA;&#x9;longmaxSeqence;&#xA;&#x9;ProcessFunction*pfTable;&#xA;&#x9;tregex*expressions;&#xA;&#x9;tmatchwhat;&#xA;};&#xA;&#xA;#endif//_LINE_REGEX_H_&#xA;&#xA;----------------------------------------------------&#xA;&#xA;----------------------LineRegex.h-------------------&#xA;&#xA;#include &amp;quot;stdafx.h&amp;quot;&#xA;&#xA;line_buffer::line_buffer ()&#xA;{&#xA;&#x9;lpFile = NULL;&#xA;}&#xA;&#xA;line_buffer::~line_buffer ()&#xA;{&#xA;&#x9;close ();&#xA;}&#xA;&#xA;int line_buffer::open (LPCTSTR lpPath)&#xA;{&#xA;&#x9;HANDLE hFile;&#xA;&#x9;DWORD dwBytes;&#xA;&#x9;__try {&#xA;&#x9;&#x9;hFile = CreateFile (lpPath, GENERIC_READ, FILE_SHARE_READ, NULL,&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;OPEN_ALWAYS, 0, NULL);&#xA;&#x9;&#x9;if (INVALID_HANDLE_VALUE == hFile)&#xA;&#x9;&#x9;&#x9;return -1;&#xA;&#x9;&#x9;FileSize = GetFileSize (hFile, NULL);&#xA;&#x9;&#x9;if (FileSize &amp;gt; 0x10000000)&#xA;&#x9;&#x9;&#x9;return -1;&#xA;&#x9;&#x9;lpFile = new BYTE[FileSize];&#xA;&#x9;&#x9;if (lpFile == NULL)&#xA;&#x9;&#x9;&#x9;return -1;&#xA;&#x9;&#x9;lpNext = (TCHAR *) lpFile;&#xA;&#x9;&#x9;if (ReadFile (hFile, lpFile, FileSize, &amp;amp;dwBytes, NULL) &amp;lt; 0)&#xA;&#x9;&#x9;&#x9;return -1;&#xA;&#x9;}&#xA;&#x9;__finally {&#xA;&#x9;&#x9;CloseHandle (hFile);&#xA;&#x9;}&#xA;&#x9;return 0;&#xA;}&#xA;&#xA;void line_buffer::close ()&#xA;{&#xA;&#x9;if (lpFile != NULL)&#xA;&#x9;&#x9;delete lpFile;&#xA;&#x9;lpFile = NULL;&#xA;&#x9;return;&#xA;}&#xA;&#xA;LPTSTR line_buffer::getline ()&#xA;{&#xA;&#x9;lpNow = lpNext;&#xA;&#x9;if (lpNow == NULL)&#xA;&#x9;&#x9;return NULL;&#xA;&#x9;while ((lpNext - (TCHAR *) lpFile) * sizeof (TCHAR) &amp;lt; FileSize) {&#xA;&#x9;&#x9;if (*lpNext == _T (&#39;n&#39;)) {&#xA;&#x9;&#x9;&#x9;*lpNext = _T (&#39;&#39;);&#xA;&#x9;&#x9;&#x9;lpNext++;&#xA;&#x9;&#x9;&#x9;return lpNow;&#xA;&#x9;&#x9;}&#xA;&#x9;&#x9;if ((*lpNext == _T (&#39;r&#39;)) &amp;amp;&amp;amp; (*(lpNext + 1) == _T (&#39;n&#39;))) {&#xA;&#x9;&#x9;&#x9;*lpNext = _T (&#39;&#39;);&#xA;&#x9;&#x9;&#x9;lpNext += 2;&#xA;&#x9;&#x9;&#x9;return lpNow;&#xA;&#x9;&#x9;}&#xA;&#x9;&#x9;lpNext++;&#xA;&#x9;}&#xA;&#x9;lpNext = NULL;&#xA;&#x9;return lpNow;&#xA;}&#xA;&#xA;long line_buffer::size ()&#xA;{&#xA;&#x9;return 0;&#xA;}&#xA;&#xA;line_regex::line_regex ()&#xA;{&#xA;&#x9;maxSeqence = 0;&#xA;&#x9;pfTable = NULL;&#xA;&#x9;expressions = NULL;&#xA;}&#xA;&#xA;line_regex::~line_regex ()&#xA;{&#xA;&#x9;maxSeqence = 0;&#xA;&#x9;if (pfTable != NULL)&#xA;&#x9;&#x9;pfTable = NULL;&#xA;&#x9;if (expressions != NULL) {&#xA;&#x9;&#x9;delete[]expressions;&#xA;&#x9;&#x9;expressions = NULL;&#xA;&#x9;}&#xA;}&#xA;&#xA;int line_regex::nextSeqence (int seqence)&#xA;{&#xA;&#x9;return seqence + 1;&#xA;}&#xA;&#xA;int line_regex::noMatch (LPTSTR strLine, int line)&#xA;{&#xA;&#x9;return 0;&#xA;}&#xA;&#xA;int line_regex::beforeProcess (LPTSTR strLine, int line)&#xA;{&#xA;&#x9;return 0;&#xA;}&#xA;&#xA;int line_regex::afterProcess (LPTSTR strLine, int line)&#xA;{&#xA;&#x9;return 0;&#xA;}&#xA;&#xA;void line_regex::registe_expression (LPCTSTR exps[])&#xA;{&#xA;&#x9;int i;&#xA;&#x9;try {&#xA;&#x9;&#x9;if (expressions != NULL) {&#xA;&#x9;&#x9;&#x9;delete[]expressions;&#xA;&#x9;&#x9;&#x9;expressions = NULL;&#xA;&#x9;&#x9;}&#xA;&#x9;&#x9;for (i = 0; exps[i]; i++);&#xA;&#x9;&#x9;maxSeqence = i;&#xA;&#x9;&#x9;expressions = new tregex[maxSeqence];&#xA;&#x9;&#x9;for (i = 0; i &amp;lt; maxSeqence; i++)&#xA;&#x9;&#x9;&#x9;expressions[i].assign (exps[i]);&#xA;&#x9;}&#xA;&#x9;catch (std::exception &amp;amp; e) {&#xA;&#x9;&#x9;cout &amp;lt;&amp;lt; &amp;quot;Error in expression: &amp;quot;&amp;quot; &amp;lt;&amp;lt; e.what () &amp;lt;&amp;lt; &amp;quot;&amp;quot;&amp;quot;&#xA;&#x9;&#x9;&#x9; &amp;lt;&amp;lt; endl;&#xA;&#x9;}&#xA;&#x9;return;&#xA;}&#xA;&#xA;int line_regex::Process (tistream &amp;amp; is)&#xA;{&#xA;&#x9;int rslt, line = 0;&#xA;&#x9;tstring str;&#xA;&#x9;try {&#xA;&#x9;&#x9;while (getline (is, str)) {&#xA;&#x9;&#x9;&#x9;line++;&#xA;&#x9;&#x9;&#x9;rslt = beforeProcess ((LPTSTR) str.c_str (), line);&#xA;&#x9;&#x9;&#x9;if (rslt &amp;lt; 0)&#xA;&#x9;&#x9;&#x9;&#x9;return rslt;&#xA;&#x9;&#x9;&#x9;if (rslt &amp;lt; 0)&#xA;&#x9;&#x9;&#x9;&#x9;continue;&#xA;&#x9;&#x9;&#x9;rslt = ProcessLine ((LPTSTR) str.c_str (), line);&#xA;&#x9;&#x9;&#x9;if (rslt &amp;lt; 0)&#xA;&#x9;&#x9;&#x9;&#x9;return rslt;&#xA;&#x9;&#x9;&#x9;rslt = afterProcess ((LPTSTR) str.c_str (), line);&#xA;&#x9;&#x9;&#x9;if (rslt &amp;lt; 0)&#xA;&#x9;&#x9;&#x9;&#x9;return rslt;&#xA;&#x9;&#x9;}&#xA;&#x9;}&#xA;&#x9;catch (std::exception &amp;amp; e) {&#xA;&#x9;&#x9;cout &amp;lt;&amp;lt; &amp;quot;Error in expression: &amp;quot;&amp;quot; &amp;lt;&amp;lt; e.what () &amp;lt;&amp;lt; &amp;quot;&amp;quot;&amp;quot;&#xA;&#x9;&#x9;&#x9; &amp;lt;&amp;lt; endl;&#xA;&#x9;}&#xA;&#x9;return 0;&#xA;}&#xA;&#xA;int line_regex::Process (line_buffer &amp;amp; lb)&#xA;{&#xA;&#x9;int rslt, line = 0;&#xA;&#x9;tstring str;&#xA;&#x9;LPTSTR lpBuffer;&#xA;&#x9;try {&#xA;&#x9;&#x9;while (lpBuffer = lb.getline ()) {&#xA;&#x9;&#x9;&#x9;line++;&#xA;&#x9;&#x9;&#x9;rslt = beforeProcess (lpBuffer, line);&#xA;&#x9;&#x9;&#x9;if (rslt &amp;lt; 0)&#xA;&#x9;&#x9;&#x9;&#x9;return rslt;&#xA;&#x9;&#x9;&#x9;if (rslt &amp;lt; 0)&#xA;&#x9;&#x9;&#x9;&#x9;continue;&#xA;&#x9;&#x9;&#x9;rslt = ProcessLine (lpBuffer, line);&#xA;&#x9;&#x9;&#x9;if (rslt &amp;lt; 0)&#xA;&#x9;&#x9;&#x9;&#x9;return rslt;&#xA;&#x9;&#x9;&#x9;rslt = afterProcess (lpBuffer, line);&#xA;&#x9;&#x9;&#x9;if (rslt &amp;lt; 0)&#xA;&#x9;&#x9;&#x9;&#x9;return rslt;&#xA;&#x9;&#x9;}&#xA;&#x9;}&#xA;&#x9;catch (std::exception &amp;amp; e) {&#xA;&#x9;&#x9;cout &amp;lt;&amp;lt; &amp;quot;Error in expression: &amp;quot;&amp;quot; &amp;lt;&amp;lt; e.what () &amp;lt;&amp;lt; &amp;quot;&amp;quot;&amp;quot;&#xA;&#x9;&#x9;&#x9; &amp;lt;&amp;lt; endl;&#xA;&#x9;}&#xA;&#x9;return 0;&#xA;}&#xA;&#xA;int line_regex::ProcessLine (LPTSTR strLine, int line)&#xA;{&#xA;&#x9;int i, rslt;&#xA;&#x9;for (i = 0; i &amp;lt; maxSeqence; i = nextSeqence (i)) {&#xA;&#x9;&#x9;if (regex_search (strLine, what, expressions[i])) {&#xA;&#x9;&#x9;&#x9;rslt = (this-&amp;gt;*(pfTable[i])) (what, line);&#xA;&#x9;&#x9;&#x9;if (rslt &amp;lt; 0)&#xA;&#x9;&#x9;&#x9;&#x9;return rslt;&#xA;#ifdef _DEBUG_OUT_&#xA;// cout &amp;lt;&amp;lt; line &amp;lt;&amp;lt; &amp;quot;:match&amp;quot; &amp;lt;&amp;lt; i &amp;lt;&amp;lt;&#xA;&#x9;&#x9;&#x9;endl;&#xA;#endif //_DEBUG_OUT_&#xA;&#x9;&#x9;&#x9;break;&#xA;&#x9;&#x9;}&#xA;&#x9;}&#xA;&#x9;if (i == maxSeqence) {&#xA;&#x9;&#x9;noMatch (strLine, line);&#xA;#ifdef _DEBUG_OUT_&#xA;// cout &amp;lt;&amp;lt; line &amp;lt;&amp;lt; &amp;quot;:no match&amp;quot; &amp;lt;&amp;lt; endl;&#xA;#endif //_DEBUG_OUT_&#xA;&#x9;}//*/&#xA;&#x9;return 0;&#xA;}&#xA;&#xA;----------------------------------------------------&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;给个例子：&lt;/p&gt;</description>
			</item>
	</channel>
</rss>
