C++ Builder 6 内置了Pcre库支持正则表达式,但这个库使用起来比较麻烦,而且只能搜索第一个匹配的文本,并且没有提供文本替换的方法。
本文通过扩展该库的方式,使支持搜索所有结果,支持字符串替代
RegExPlus.h
//---------------------------------------------------------------------------
#ifndef RegExPlusH
#define RegExPlusH
#include <pcre.h>
//---------------------------------------------------------------------------
class RegExPlus : public TObject
{
private:
pcre *re;
String m_RegStr;
const char *m_pSearceBuf;
String m_pSearceStr;
int m_Options;
int nErrOffset;
int m_pResult[1024];
int m_ResultCount;
String m_ErrMsg;
bool __fastcall GetInitSucc();
String __fastcall GetRegExStr();
void __fastcall SetRegExStr(const String &RegExStr);
void __fastcall SetRegExOpt(int Options);
void __fastcall Clear();
String __fastcall GetMatchStr(int Index);
int __fastcall GetMatchLength(int Index);
String __fastcall GetErrorMsg();
bool __fastcall search(const char *Str,int Offset,int Count,int Options);
public:
//搜索选项
static int CASELESS; //忽略大小写
static int MULTILINE; //多行模式,主要影响修饰符^(行开始) 和 $(行结束)
static int DOTALL; //如果设定了此修正符,模式中的圆点元字符(.)匹配所有的字符,包括换行符。没有此设定的话,则不包括换行符
static int EXTENDED; //如果设定了此修正符,模式中的空白字符除了被转义的或在字符类中的以外完全被忽略,在未转义的字符类之外的 # 以及下一个换行符之间的所有字符,包括两头,也都被忽略。这和 Perl 的 /x 修正符是等效的,使得可以在复杂的模式中加入注释。然而注意,这仅适用于数据字符。空白字符可能永远不会出现于模式中的特殊字符序列,例如引入条件子模式的序列 (?( 中间。
static int ANCHORED; //如果设定了此修正符,模式被强制为“anchored”,即强制仅从目标字符串的开头开始匹配。
static int DOLLAR_ENDONLY; //如果设定了此修正符,模式中的美元元字符仅匹配目标字符串的结尾。没有此选项时,如果最后一个字符是换行符的话,美元符号也会匹配此字符之前(但不会匹配任何其它换行符之前)
static int EXTRA; //此修正符启用了一个 PCRE 中与 Perl 不兼容的额外功能。模式中的任何反斜线后面跟上一个没有特殊意义的字母导致一个错误,从而保留此组合以备将来扩充。默认情况下,和 Perl 一样,一个反斜线后面跟一个没有特殊意义的字母被当成该字母本身。当前没有其它特性受此修正符控制。
static int NOTBOL;
static int NOTEOL;
static int UNGREEDY; //本修正符反转了匹配数量的值使其不是默认的重复,而变成在后面跟上"?"才变得重复。这和 Perl 不兼容。也可以通过在模式之中设定 (?U) 修正符或者在数量符之后跟一个问号(如 .*?)来启用此选项。
static int SEARCE_ALL; //查找所有结果,否则只查到第一个
static int SUB_RESULT; //同时返回圆括号内的查找结果,每对圆括号多一个结果
public:
__fastcall RegExPlus();
//初始化正则表达式类
__fastcall RegExPlus(const String &RegExStr,int Options=0);
__fastcall ~RegExPlus();
bool __fastcall SetRegExStr(const String &RegExStr,int Options);
const char *__fastcall GetMatch(int Index);
//查找字符串,从Offset开始,一共搜索多少字符,如果Count为0,则表示搜索到结尾
bool __fastcall search(const char *Str,int Offset=0,int Count=0);
//查找字符串,使用AnsiString
bool __fastcall search(const String &Str,int Offset=0);
//字符串替代,返回替代的结果
String __fastcall Reaplace(const String &Str,const String &RepalceStr,int Offset=0);
__published: // IDE-managed Components
//返回正则表达式是否初始化成功
__property bool InitSuccess = { read=GetInitSucc };
//获取或设置正侧表达式
__property String RegExStr = { read=GetRegExStr, write=SetRegExStr };
//获取或设置正侧表达式选项
__property int Options = { read=m_Options, write=SetRegExOpt };
//返回搜索匹配的数量
__property int MatchCount = { read=m_ResultCount };
//返回匹配的字符串数组
__property String MatchStr[int Idx] = { read=GetMatchStr };
//返回匹配的字符串的长度
__property int MatchLength[int Idx] = { read=GetMatchLength };
//正则表达式错误位置
__property int ErrorStart = { read=nErrOffset };
//正则表达式错误的内容
__property String ErrorMsg = { read=m_ErrMsg };
};
#endif
Unit1.cpp
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "RegExPlus.h"
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TFrmMain *FrmMain;
//---------------------------------------------------------------------------
__fastcall TFrmMain::TFrmMain(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TFrmMain::btFindClick(TObject *Sender)
{
int Options = 0;
if(cbMARCHALL->Checked)
Options |= RegExPlus::SEARCE_ALL;
if(cbSUB_RESULT->Checked)
Options |= RegExPlus::SUB_RESULT;
if(cbCASELESS->Checked)
Options |= RegExPlus::CASELESS;
if(cbMULTILINE->Checked)
Options |= RegExPlus::MULTILINE;
//初始化正则表达式
RegExPlus *regex = new RegExPlus(edRegEx->Text, Options);
if(regex->InitSuccess)
{
Memo2->Text = "";
//查找匹配项
if(regex->search(Memo1->Text))
{
//显示匹配结果
for(int i=0; i<regex->MatchCount; i++)
{
Memo2->Lines->Add(String().sprintf("%2d: %s", i, regex->MatchStr[i]));
}
}
}
else
{
Memo2->Text = String().sprintf("正则表示式错误,位置:%2d: %s",regex->ErrorStart,regex->ErrorMsg);
}
delete regex;
}
//---------------------------------------------------------------------------
void __fastcall TFrmMain::btRepalceClick(TObject *Sender)
{
int Options = 0;
if(cbMARCHALL->Checked)
Options |= RegExPlus::SEARCE_ALL;
if(cbSUB_RESULT->Checked)
Options |= RegExPlus::SUB_RESULT;
if(cbCASELESS->Checked)
Options |= RegExPlus::CASELESS;
if(cbMULTILINE->Checked)
Options |= RegExPlus::MULTILINE;
//初始化正则表达式
RegExPlus *regex = new RegExPlus(edRegEx->Text, Options);
if(regex->InitSuccess)
{
//字符串查找并替换
Memo2->Text = regex->Reaplace(Memo1->Text,edReplaceStr->Text,0);
}
else
{
Memo2->Text = String().sprintf("正则表示式错误,位置:%2d: %s",regex->ErrorStart,regex->ErrorMsg);
}
delete regex;
}
//---------------------------------------------------------------------------
Unit1.h
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
class TFrmMain : public TForm
{
__published: // IDE-managed Components
TMemo *Memo1;
TMemo *Memo2;
TLabel *Label1;
TEdit *edRegEx;
TLabel *Label2;
TLabel *Label3;
TButton *btRepalce;
TButton *btFind;
TCheckBox *cbSUB_RESULT;
TCheckBox *cbMARCHALL;
TCheckBox *cbCASELESS;
TCheckBox *cbMULTILINE;
TLabel *Label4;
TEdit *edReplaceStr;
void __fastcall btFindClick(TObject *Sender);
void __fastcall btRepalceClick(TObject *Sender);
private: // User declarations
public: // User declarations
__fastcall TFrmMain(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TFrmMain *FrmMain;
//---------------------------------------------------------------------------
#endif
代码下载
https://download.youkuaiyun.com/download/guanshangming/18416082