プログラミング工房 > HSP > サンプルモジュール > 

正規表現ライブラリ、"bregexp.dll"を利用する

 以下のスクリプトはbabaqさん作の正規表現ライブラリ、"BREGEXP DLL"を簡単に利用するためのモジュールです。"BREGEXP DLL"はPerl5互換の正規表現を使って文字列の検索・置換・変換・分割するための関数を備えており、このモジュールを経由することでDLLで扱われているポインタや構造体を意識することなくそれらの機能を利用できます。このDLLで使える正規表現の仕様については、"BREGEXP DLL"のホームページをご覧下さい。

 >> ダウンロード (ブラウザで見ると文字化けしますが、データは正常です)

/***********************************************************

	bregexp.dllラッパーモジュール

	【2007/09/12 更新】

	【使い方】

		利用したいスクリプトでインクルードし、【命令一覧】にある命令を直接呼び出す。
		このファイル末尾にテスト用サンプルスクリプトあり。

	【命令一覧】

		●パターンマッチ検索(検索開始位置以降、先頭のみ)
;		#deffunc brex_match str rex_, var target_, int srchpos_, var ret_idx_, var ret_len_
			rex_		: 正規表現文字列またはそれを代入した変数
			target_		: 処理対象文字列を代入した変数
			srchpos_		: 処理対象文字列の検索開始位置(バイト単位。先頭=0)またはそれを代入した変数
			ret_idx_		: 処理対象文字列内でのマッチ文字列の開始位置を受け取るための数値変数
					  (マッチしなかった場合=-1)
			ret_len_		: ret_idx_に対応したマッチ文字列の長さを受け取るための数値変数
					  (マッチしなかった場合=-1)
			戻り値(stat)	: マッチしたかどうか(1=yes / 0=no)またはエラー(-1)

		●パターンマッチ検索(検索開始位置以降、すべて)
;		#deffunc brex_gmatch str rex_, var target_, int srchpos_, array ret_idxes_, array ret_lens_
			rex_		: 正規表現文字列またはそれを代入した変数
			target_		: 処理対象文字列を代入した変数
			srchpos_		: 処理対象文字列の検索開始位置(バイト単位。先頭=0)またはそれを代入した変数
			ret_idxes_	: 処理対象文字列内でのマッチ文字列の開始位置を受け取るための数値変数(配列)
					  (末尾=-1)
			ret_lens_		: ret_idx_に対応したマッチ文字列の長さを受け取るための数値変数(配列)
					  (末尾=-1)
			戻り値(stat)	: マッチした回数またはエラー(-1)

		●置換
;		#deffunc brex_subst str rex_, var target_, var ret_subst_
			rex_		: 正規表現文字列またはそれを代入した変数
			target_		: 処理対象文字列を代入した変数
			ret_subst_	: 置換後文字列を受け取るための文字列変数
					  (1ヶ所以上置換されたときのみ有効)
			戻り値(stat)	: 置換された回数またはエラー(-1)

		●変換
;		#deffunc brex_trans str rex_, var target_, var ret_trans_
			rex_		: 正規表現文字列またはそれを代入した変数
			target_		: 処理対象文字列を代入した変数
			ret_trans_	: 変換後文字列を受け取るための文字列変数
					  (1ヶ所以上変換されたときのみ有効)
			戻り値(stat)	: 変換された回数(文字数)またはエラー(-1)

		●分割
;		#deffunc brex_split str rex_, var target_, int limit_, array ret_split_
			rex_		: 正規表現文字列またはそれを代入した変数
			target_		: 処理対象文字列を代入した変数
			limit_		: 戻す配列数の最大値(0=無制限)
			ret_split_	: 分割された文字列を受け取るための文字列変数(配列)
					  (エラーにならなかったときのみ有効)
			戻り値(stat)	: 分割された文字列の数(配列要素数)またはエラー(-1)

		●バージョン文字列を取得
;		#deffunc brex_getver var ret_verstr_
			ret_verstr_	: バージョン文字列を受け取るための変数
			戻り値(stat)	: バージョン文字列の長さ


	【bregexp.dll公開元】
		http://www.hi-ho.ne.jp/babaq/bregexp.html

***********************************************************/
#ifndef	__GM_BREGEXP__
#define	global	__GM_BREGEXP__


#uselib	"bregexp.dll"
	#func global BMatch		"BMatch"	sptr,sptr,sptr,sptr,sptr
	#func global BSubst		"BSubst"	sptr,sptr,sptr,sptr,sptr
	#func global BTrans		"BTrans"	sptr,sptr,sptr,sptr,sptr
	#func global BSplit		"BSplit"	sptr,sptr,sptr,int,sptr,sptr
	#func global BRegfree		"BRegfree"	sptr
	#func global BRegexpVersion		"BRegexpVersion"
#uselib	"msvcrt.dll"
	#cfunc global strlen_c		"strlen"	sptr


#module bregexp_dll

	#const	NULL			0
	#const	TRUE			1
	#const	FALSE			0

	#const	BREGEXP_ERROR		-1
	
	#const	INVALID_INDEX		-1
	#const	INVALID_LEN		-1
	
	#const	MSG_SIZE			256
	
	#const	VARTYPE_STR		2	; dupptr命令引数
	
	#const	POINTER_SIZE		4	; ポインタ(メモリアドレス)のサイズを4バイト(32ビット)で
						; 決めうちしている。
	#const	BREGEXP_SIZE		44	; BREGEXP構造体サイズ
	#const	BREGEXP_OUTP		0
	#const	BREGEXP_OUTENDP		1
	#const	BREGEXP_SPLITCTR		2
	#const	BREGEXP_SPLITP		3
	#const	BREGEXP_RSV1		4
	#const	BREGEXP_PARAP		5
	#const	BREGEXP_PARAENDP		6
	#const	BREGEXP_TRANSTBLP		7
	#const	BREGEXP_STARTP		8
	#const	BREGEXP_ENDP		9
	#const	BREGEXP_NPARENS		10
	
#global


#module
/**********************************************************/
//
// BREGEXP構造体からマッチ文字列の開始位置と終了位置を取得
//
/**********************************************************/
#deffunc _get_bregexp_match int bregexp_ptr_, var ret_start_ptr_, var ret_end_ptr_

	dupptr	bregexp,        bregexp_ptr_,                        BREGEXP_SIZE@bregexp_dll
	dupptr	ret_start_ptr_, bregexp(BREGEXP_STARTP@bregexp_dll), POINTER_SIZE@bregexp_dll
	dupptr	ret_end_ptr_,   bregexp(BREGEXP_ENDP@bregexp_dll),   POINTER_SIZE@bregexp_dll

	return
#global


#module
/**********************************************************/
//
// パターンマッチ検索
//
/**********************************************************/
#deffunc brex_match str rex_, var target_, int srchpos_, var ret_idx_, var ret_len_

	rex	= rex_
	target	= target_
	ret_idx_	= INVALID_INDEX@bregexp_dll
	ret_len_	= INVALID_LEN@bregexp_dll

	srchpos		= srchpos_		; 検索開始位置
	bregexp_ptr	= NULL@bregexp_dll		; BREGEXP構造体用
	sdim	msg, MSG_SIZE@bregexp_dll		; 用途不明

	BMatch	rex, (varptr(target) + srchpos), (varptr(target) + strlen(target)), varptr(bregexp_ptr), varptr(msg)
	matchresult	= stat		; マッチしたかどうか(1=yes / 0=no)またはエラー(-1)
	if matchresult > 0 {
		_get_bregexp_match	bregexp_ptr, start_ptr, end_ptr	; マッチ文字列の開始位置と終了位置を取得
		ret_idx_	= start_ptr - varptr(target)
		ret_len_	= end_ptr   - varptr(target) - ret_idx_
	}
	
	if bregexp_ptr {
		BRegfree	bregexp_ptr
	}

	return	matchresult
#global


#module
/**********************************************************/
//
// パターンマッチ検索(すべて)
//
/**********************************************************/
#deffunc brex_gmatch str rex_, var target_, int srchpos_, array ret_idxes_, array ret_lens_

	rex		= rex_
	target		= target_
	targetlen		= strlen(target)
	dim	ret_idxes_,	1
	dim	ret_lens_,	1
	matchcnt	= 0
	srchpos	= srchpos_			; 検索開始位置

	repeat
		ret_idxes_(cnt)	= INVALID_INDEX@bregexp_dll
		ret_lens_(cnt)	= INVALID_LEN@bregexp_dll
		if srchpos >= targetlen {
			break
		}

		bregexp_ptr	= NULL@bregexp_dll	; BREGEXP構造体用
		sdim	msg, MSG_SIZE@bregexp_dll	; 用途不明
		BMatch	rex, (varptr(target) + srchpos), (varptr(target) + strlen(target)), varptr(bregexp_ptr), varptr(msg)
		matchresult	= stat		; マッチしたかどうか(1=yes / 0=no)またはエラー(-1)
		if matchresult <= 0 {
			if matchresult = BREGEXP_ERROR@bregexp_dll {
				matchcnt	= matchresult
			}
			break
		}

		matchcnt	++
		_get_bregexp_match	bregexp_ptr, start_ptr, end_ptr	; マッチ文字列の開始位置と終了位置+1を取得
		ret_idxes_(cnt)	= start_ptr - varptr(target)
		ret_lens_(cnt)	= end_ptr   - varptr(target) - ret_idxes_(cnt)
		srchpos		= end_ptr   - varptr(target)

		if bregexp_ptr {
			BRegfree	bregexp_ptr
		}
	loop

	return	matchcnt
#global


#module
/**********************************************************/
//
// BREGEXP構造体から処理結果文字列の開始位置と終了位置を取得
//
/**********************************************************/
#deffunc _get_bregexp_out int bregexp_ptr_, var ret_start_ptr_, var ret_end_ptr_

	dupptr	bregexp, bregexp_ptr_, BREGEXP_SIZE@bregexp_dll
	ret_start_ptr_	= bregexp(BREGEXP_OUTP@bregexp_dll)
	ret_end_ptr_	= bregexp(BREGEXP_OUTENDP@bregexp_dll)

	return
#global


#module
/**********************************************************/
//
// 置換
//
/**********************************************************/
#deffunc brex_subst str rex_, var target_, var ret_subst_

	rex		= rex_
	target		= target_
	ret_subst_	= ""

	bregexp_ptr	= NULL@bregexp_dll		; BREGEXP構造体用
	sdim	msg, MSG_SIZE@bregexp_dll		; 用途不明

	BSubst	rex, varptr(target), (varptr(target) + strlen(target)), varptr(bregexp_ptr), varptr(msg)
	substcnt	= stat		; 置換した回数またはエラー(-1)
	if substcnt > 0 {
		_get_bregexp_out	bregexp_ptr, start_ptr, end_ptr		; 置換後文字列の開始位置と終了位置を取得
		dupptr	subst_result, start_ptr, (end_ptr - start_ptr + 1), VARTYPE_STR@bregexp_dll
		ret_subst_	= subst_result
	}

	if bregexp_ptr {
		BRegfree	bregexp_ptr
	}

	return	substcnt
#global


#module
/**********************************************************/
//
// 変換
//
/**********************************************************/
#deffunc brex_trans str rex_, var target_, var ret_trans_

	rex		= rex_
	target		= target_
	ret_trans_	= ""

	bregexp_ptr	= NULL@bregexp_dll		; BREGEXP構造体用
	sdim	msg, MSG_SIZE@bregexp_dll		; 用途不明

	BTrans	rex, varptr(target), (varptr(target) + strlen(target)), varptr(bregexp_ptr), varptr(msg)
	transcnt	= stat		; 変換した回数またはエラー(-1)
	if transcnt > 0 {
		_get_bregexp_out	bregexp_ptr, start_ptr, end_ptr		; 変換後文字列の開始位置と終了位置を取得
		dupptr	subst_result, start_ptr, (end_ptr - start_ptr + 1), VARTYPE_STR@bregexp_dll
		ret_trans_	= subst_result
	}

	if bregexp_ptr {
		BRegfree	bregexp_ptr
	}

	return	transcnt
#global


#module
/**********************************************************/
//
// 分割
//
/**********************************************************/
#deffunc brex_split str rex_, var target_, int limit_, array ret_split_

	rex		= rex_
	target		= target_
	ret_split_	= ""

	bregexp_ptr	= NULL@bregexp_dll		; BREGEXP構造体用
	sdim	msg, MSG_SIZE@bregexp_dll		; 用途不明

	BSplit	rex, varptr(target), (varptr(target) + strlen(target)), limit_, varptr(bregexp_ptr), varptr(msg)
	splitcnt	= stat		; 分割された文字列の数またはエラー(-1)
	if splitcnt > 0 {
		dupptr	bregexp, bregexp_ptr, BREGEXP_SIZE@bregexp_dll
		i	= 0			; BREGEXP構造体のsplitpメンバ用インデックス
		repeat	splitcnt 	; = bregexp(BREGEXP_SPLITCTR@bregexp_dll)
			; 分割された文字列の開始位置を取得
			p1	= (bregexp(BREGEXP_SPLITP@bregexp_dll) + i * POINTER_SIZE@bregexp_dll)
			dupptr	ptr_1, p1, POINTER_SIZE@bregexp_dll
			; 分割された文字列の終了位置+1を取得
			p1	= (bregexp(BREGEXP_SPLITP@bregexp_dll) + (i + 1) * POINTER_SIZE@bregexp_dll)
			dupptr	ptr_2, p1, POINTER_SIZE@bregexp_dll
			; BREGEXP構造体のsplitpメンバは開始位置と終了位置+1のアドレスが
			; 交互に並んだ配列の先頭を指しているので2ずつずらす。
			i	+= 2

			len	= ptr_2 - ptr_1
			if len < 1 {
				ret_split_(cnt)	= ""
				continue
			}
			dupptr	tmpbuf, ptr_1, len		; 分割された文字列の末尾がヌル文字ではないため
							; VARTYPE_STR@bregexp_dllは指定できない。
			sdim	splittedtext, len + 1
			memcpy	splittedtext, tmpbuf, len, 0, 0
			ret_split_(cnt)	= splittedtext
		loop
	}

	if bregexp_ptr {
		BRegfree	bregexp_ptr
	}

	return	splitcnt
#global


#module
/**********************************************************/
//
// バージョン文字列を取得
//
/**********************************************************/
#deffunc brex_getver var ret_verstr_

	BRegexpVersion
	verstr_ptr	= stat
	len		= strlen_c(verstr_ptr)
	dupptr		verstr, verstr_ptr, (len + 1), VARTYPE_STR@bregexp_dll
	ret_verstr_	= verstr

	return	strlen(ret_verstr_)
#global


#endif



	/* テスト用サンプルスクリプト */

;	text	= "Yokohama 045-222-1111  Osaka 06-5555-6666  Tokyo 03-1111-9999"
;
;	mes	"[brex_match]"
;	brex_match	"/(03|045)-(\\d{3,4})-(\\d{4})/", text, 0, idx, len
;	ret	= stat
;	switch	ret
;	case	BREGEXP_ERROR@bregexp_dll
;		mes	"p1,p2,p3いずれかの内容が不正です。"
;		swbreak
;	case	0
;		mes	"マッチする文字列はありませんでした。"
;		swbreak
;	default
;		mes "idx: " + idx + " / " + "len: " + len + " / " + "matchstr: \"" + strmid(text, idx, len) + "\""
;	swend
;
;	mes	"\n[brex_gmatch]"
;	brex_gmatch	"/(03|045)-(\\d{3,4})-(\\d{4})/", text, 0, idxes, lens
;	ret	= stat
;	switch	ret
;	case	BREGEXP_ERROR@bregexp_dll
;		mes	"p1,p2,p3いずれかの内容が不正です。"
;		swbreak
;	case	0
;		mes	"マッチする文字列はありませんでした。"
;		swbreak
;	default
;		mes	"cnt: " + ret
;		repeat	length(idxes)
;			if idxes(cnt) = INVALID_INDEX@bregexp_dll {		; 配列末尾
;				break
;			}
;			messtr	=	"idx(" + cnt + "): " + idxes(cnt)
;			messtr	+=	" / " + "len(" + cnt + "): " + lens(cnt)
;			messtr	+=	" / " + "matchstr(" + cnt + "): \"" + strmid(text, idxes(cnt), lens(cnt)) + "\""
;			mes		messtr
;		loop
;	swend
;
;	mes	"\n[brex_subst]"
;	brex_subst	"s/(\\d\\d)-\\d{4}-\\d{4}/$1-xxxx-xxxx/g", text, substtext
;	ret	= stat
;	switch	ret
;	case	BREGEXP_ERROR@bregexp_dll
;		mes	"p1,p2いずれかの内容が不正です。"
;		swbreak
;	case	0
;		mes	"置換できる文字列はありませんでした。"
;		swbreak
;	default
;		mes	"cnt: " + ret
;		mes	"result: \"" + substtext + "\""
;	swend
;
;	mes	"\n[brex_trans]"
;	brex_trans	"tr/A-Z0-9/a-zx/", text, transtext
;	ret	= stat
;	switch	ret
;	case	BREGEXP_ERROR@bregexp_dll
;		mes	"p1,p2いずれかの内容が不正です。"
;		swbreak
;	case	0
;		mes	"変換できる文字列はありませんでした。"
;		swbreak
;	default
;		mes	"cnt: " + ret
;		mes	"result: \"" + transtext + "\""
;	swend
;
;	mes	"\n[brex_split]"
;	brex_split	"/ *\\d{2,3}-\\d{3,4}-\\d{4} */", text, 0, texts
;	ret	= stat
;	switch	ret
;	case	BREGEXP_ERROR@bregexp_dll
;		mes	"p1,p2いずれかの内容が不正です。"
;		swbreak
;	default
;		mes	"cnt: " + ret
;		splittext	= ""
;		foreach	texts
;			splittext	+= "\"" + texts(cnt) + "\" "
;		loop
;		mes	"result: " + splittext
;	swend
;
;	mes	"\n[brex_getver]"
;	brex_getver	verstr
;	ret	= stat
;	mes	"len: " + ret
;	mes	"verstr: " + verstr
;
;	mes	"\nend"