Private Declare Function Match Lib "bregexp" _ (szRegstr As String, szTarget As String) As String Private Declare Function MatchEx Lib "bregexp" _ (szRegstr As String, szTarget As String, mode As Long) As Variant Private Declare Function Replace Lib "bregexp" _ (szRegstr As String, szTarget As String) As String Private Declare Function Translate Lib "bregexp" _ (szRegstr As String, szTarget As String, ret As String) As Long Private Declare Function Split Lib "bregexp" _ (szRegstr As String, szTarget As String, limit As Long) As Variant
\ 次のメタ文字をクォートする(取り消す) ^ 行の最初にマッチする . (改行以外の) すべての文字にマッチする $ 行の終わりにマッチする | 選択 () グループ化 [] 文字クラス \w 単語」の構成文字 (英数字と "_") にマッチ \W 単語の構成文字以外にマッチ \s 空白文字にマッチ \S 空白文字以外にマッチ \d 数字にマッチ \D 数字以外にマッチ \b 単語の境界にマッチ \B 単語の境界以外にマッチ \A 文字列の最初にのみマッチ \Z 文字列の最後にのみマッチ \t タブ \n 改行 \r 復帰 \f 改ページ \a アラーム (ベル) \e エスケープ \033 8 進数で表した文字 \x1b 16 進数で表した文字 \c[ コントロール文字 直前の文字の数量子: * 0 回以上にマッチ + 1 回以上にマッチ ? 1 回または 0 回にマッチ {n} ちょうど n 回にマッチ {n,} n 回以上にマッチ {n,m} n 回以上 m 回以下にマッチ 修飾子は、つぎのようなものです。 k 文字を日本語(SJIS)として扱う(Perlにはこの修飾子はありません) m 文字列を複数行として扱う(メタ文字$の処理結果に影響を及ぼします) g 置換:グローバルな置換 c 変換:SEARCHLIST を補集合にする d 変換:見つかったが置換されなかった文字を削除する s 変換:置換された文字が重なったときに圧縮する
●VBなどでパターンに変数名を書いても展開されません ●メタ文字 \G 前回の m//g が終わったところにのみマッチ ●修飾子(パターンの右側につけるパラメータ) o 一度だけコンパイル x 拡張正規表現を使用する e 式の右側の評価を行なう
#include "bregexp.h" // Regular Expression DLL =================== bregexp.h 開始 ====================================== #ifdef _BREGEXP_ #define BREGEXPAPI __declspec(dllexport) #else #define BREGEXPAPI __declspec(dllimport) #endif typedef struct bregexp { const char *outp; // BSubst 置換データの先頭ポインタ const char *outendp; // BSubst 置換データの最終ポインタ+1 const int splitctr; // BSplit 配列数 const char **splitp; // BSplit データポインタ int rsv1; // リザーブ 自由に使用可能 char *parap; // パターンデータポインタ char *paraendp; // パターンデータポインタ+1 char *transtblp; // BTrans 変換テーブルポインタ char **startp; // マッチしたデータの先頭ポインタ char **endp; // マッチしたデータの最終ポインタ+1 int nparens; // パターンの中の() の数。 $1,$2, を調べるときに使用 } BREGEXP; #if defined(__cplusplus) extern "C" { #endif BREGEXPAPI int BMatch(char* str,char *target,char *targetendp, BREGEXP **rxp,char *msg) ; BREGEXPAPI int BSubst(char* str,char *target,char *targetendp, BREGEXP **rxp,char *msg) ; BREGEXPAPI int BTrans(char* str,char *target,char *targetendp, BREGEXP **rxp,char *msg) ; BREGEXPAPI int BSplit(char* str,char *target,char *targetendp, int limit,BREGEXP **rxp,char *msg); BREGEXPAPI void BRegfree(BREGEXP* rx); BREGEXPAPI char* BRegexpVersion(void); #if defined(__cplusplus) } #endif #undef BREGEXPAPI =================== bregexp.h 終り ======================================
char msg[256]; BREGEXP *rxp = NULL; int matched = BMatch("m/abc/",szTarget, szTarget+strlen(szTarget),&rxp,msg);
class BregPool { public: BregPool(int max){ m_nmax = max; m_rxpool = new BREGEXP*[m_nmax]; ZeroMemory(m_rxpool,sizeof(BREGEXP*)*m_nmax); }; ~BregPool() { Free(); }; void Free() { if (m_rxpool == 0) return; for (int i = 0;i < m_nmax;i++) { if (m_rxpool[i]) BRegfree(m_rxpool[i]); } delete [] m_rxpool; m_rxpool = NULL; }; BREGEXP* Get(char *regstr) { BREGEXP *r; for (int i = 0;i < m_nmax;i++) { r = m_rxpool[i]; if (r == 0) break; if (r->parap == 0) break; // Check same Regular Expression if (memcmp(regstr,r->parap,(r->paraendp - r->parap) + 1) == 0) return r; // we got !!! } if (i > m_nmax - 1) i = m_nmax - 1; if (m_rxpool[i]) return m_rxpool[i]; char msg[80]; char p[] = " "; // Make Compile Block BMatch(regstr,p,p+1,&m_rxpool[i],msg); return m_rxpool[i]; } private: int m_nmax; BREGEXP **m_rxpool; }; BregPoolクラスの使い方: static BregPool bpool(8); // プール数を8 char patern1[] = "tr/A-Z0-9/a-zx/g"; BREGEXP *rxp = bpool.Get(patern1); int pos = 0; // 検索ポジション while (BMatch(patern1,t1+pos,t1+lstrlen(t1),&rxp,msg)) { // BRegfree関数は、BregPoolクラスのデストラクタが // 呼出すので明示的に呼出す必要はない
char msg[80]; // メッセージ領域 BREGEXP *rxp = NULL; // 必ずクリアしておくこと // 検索文字サンプル char t1[] = " Yokohama 045-222-1111 Osaka 06-5555-6666 Tokyo 03-1111-9999 "; char patern1[] = "/(03|045)-(\\d{3,4})-(\\d{4})/"; // /(03|045)-(\d{3,4})-(\d{4})/ // 03か045 の電話番号を検索 // カッコ() は、それぞれの番号を記憶することを意味する int pos = 0; // 検索ポジション while (BMatch(patern1,t1+pos,t1+lstrlen(t1),&rxp,msg)) { TRACE1("data=%s\n",t1+pos); // 検索される文字 TRACE1("found=%s\n",rxp->startp[0]); // マッチ文字列 TRACE1("length=%d\n",rxp->endp[0] - rxp->startp[0]); // マッチ文字数 for (int i = 1;i <= rxp->nparens;i++) { // カッコ内のデータ TRACE2("$%d = %s\n",i,rxp->startp[i]); TRACE2("$%d length = %d\n",i,rxp->endp[i]-rxp->startp[i]); } pos = rxp->endp[0] - t1; // 次の文字の検索位置 } pos = 0; char t2[] = " abcdabce abcdabcd abcdabcf abcgabcg "; char patern2[] = "/abc(.)abc\\1/"; // 検索中でのパターン記憶の例 while(BMatch(patern2,t2+pos,t2+lstrlen(t2),&rxp,msg)) { TRACE1("data=%s\n",t2); // 検索される文字 TRACE1("found=%s\n",rxp->startp[0]); // マッチ文字列 TRACE1("length=%d\n",rxp->endp[0] - rxp->startp[0]); // マッチ文字数 for (int i = 1;i <= rxp->nparens;i++) { // カッコ内のデータ TRACE2("$%d = %s\n",i,rxp->startp[i]); TRACE2("$%d length = %d\n",i,rxp->endp[i]-rxp->startp[i]); } pos = rxp->endp[0] - t2; // 次の文字の検索位置 } if (rxp) // コンパイルブロックの開放 BRegfree(rxp); // 忘れないように TRACE結果: data= Yokohama 045-222-1111 Osaka 06-5555-6666 Tokyo 03-1111-9999 found=045-222-1111 Osaka 06-5555-6666 Tokyo 03-1111-9999 length=12 $1 = 045-222-1111 Osaka 06-5555-6666 Tokyo 03-1111-9999 $1 length = 3 $2 = 222-1111 Osaka 06-5555-6666 Tokyo 03-1111-9999 $2 length = 3 $3 = 1111 Osaka 06-5555-6666 Tokyo 03-1111-9999 $3 length = 4 data= Osaka 06-5555-6666 Tokyo 03-1111-9999 found=03-1111-9999 length=12 $1 = 03-1111-9999 $1 length = 2 $2 = 1111-9999 $2 length = 4 $3 = 9999 $3 length = 4 data= abcdabce abcdabcd abcdabcf abcgabcg found=abcdabcd abcdabcf abcgabcg length=8 $1 = dabcd abcdabcf abcgabcg $1 length = 1 data= abcdabce abcdabcd abcdabcf abcgabcg found=abcgabcg length=8 $1 = gabcg $1 length = 1
char msg[80]; // メッセージ領域 BREGEXP *rxp = NULL; // 必ずクリアしておくこと // 置換文字サンプル char t1[] = " Yokohama 045-222-1111 Osaka 06-5555-6666 Tokyo 03-1111-9999 "; char patern1[] = "s/(\\d\\d)-\\d{4}-\\d{4}/$1-xxxx-xxxx/g"; int ctr; if (ctr = BSubst(patern1,t1,t1+lstrlen(t1),&rxp,msg)) { TRACE2("after(%d)=%s\n",ctr,rxp->outp); // 置換したパターン数と文字列 TRACE1("length=%d\n",rxp->outendp - rxp->outp); // 置換後の文字数 } if (rxp) // コンパイルブロックの開放 BRegfree(rxp); // 忘れないように TRACE結果: after(2)= Yokohama 045-222-1111 Osaka 06-xxxx-xxxx Tokyo 03-xxxx-xxxx length=63
char msg[80]; // メッセージ領域 BREGEXP *rxp = NULL; // 必ずクリアしておくこと // 変換文字サンプル char t1[] = " Yokohama 045-222-1111 Osaka 06-5555-6666 Tokyo 03-1111-9999 "; char patern1[] = "tr/A-Z0-9/a-zx/g"; int ctr; if (ctr = BTrans(patern1,t1,t1+lstrlen(t1),&rxp,msg)) { TRACE2("after(%d)=%s\n",ctr,rxp->outp); // 変換した文字数と文字列 TRACE1("length=%d\n",rxp->outendp - rxp->outp); // 変換後の文字数 } if (rxp) // コンパイルブロックの開放 BRegfree(rxp); // 忘れないように TRACE結果: after(33)= yokohama xxx-xxx-xxxx osaka xx-xxxx-xxxx tokyo xx-xxxx-xxxx length=63
static BregPool bpool(8); char msg[80]; char t1[] = " Yokohama 045-222-1111 Osaka 06-5555-6666 Tokyo 03-1111-9999 "; char patern1[] = "/ *\\d{2,3}-\\d{3,4}-\\d{4} */"; BREGEXP *rxp = bpool.Get(patern1); int splitcnt = BSplit(patern1,t1,t1+lstrlen(t1),0,&rxp,msg); if (splitcnt > 0 ) { int i = 0; for (int j = 0;j < splitcnt;j++) { int len = rxp->splitp[i+1] - rxp->splitp[i]; char *tp = (char*)rxp->splitp[i]; char ch = tp[len]; // save delmitter tp[len] = 0; // set stopper TRACE3("len=%d [%d]=%s\n",len,j,tp); tp[len] = ch; // restore the char i += 2; } } TRACE結果: len=9 [0]= Yokohama len=5 [1]=Osaka len=5 [2]=Tokyo