スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書く事で広告が消せます。

part31 - 文字列 の 否定

正規表現 否定 文字列

前のページ    次のページ


いろいろな環境の中には、先読み否定である (?! ) が

使えない環境があります。 このような環境では、

「ABC」 という文字列を含まない


というような、文字列の否定をする正規表現を作るのは

とても難しい作業になります

※ (?! ) が使える環境での作り方は こちら



では、例として、

以下のようなテキストにマッチする正規表現を考えてみましょう★

・ テキストの先頭が AA から始まる

・ テキストの末尾が AA で終わる

・ 先頭の AA と、末尾の AA との間に挟まれた文字列の中には
 AA が存在しない



ちなみに、

"AAAAA" というテキストの場合、中に挟まれた文字列が
 A の1文字だけなので、マッチするものとします


▽ マッチさせたいテキストの図
マッチさせたいテキストの図


このような場合、

まず、以下のように正規表現に使えそうなパーツを書き出します

^AA ・・・ テキストの先頭にある AA にマッチする表現
AA$ ・・・ テキストの末尾にある AA にマッチする表現
A[^A] ・・・ ”A 1文字” の後ろに ”A以外の1文字” が
          あれば、この2文字にマッチする表現
[^A]  ・・・ ”A以外の1文字” にマッチする表現


(重要) A[^A] は 2文字 にマッチするということを忘れないで下さい


ちなみに、 A[^A] と [^A] は以下のような関係になっています

・ ある文字が A 以外ならば、 [^A] にマッチする

・ ある文字が A であり、次の文字が A 以外ならば、
 この2文字が A[^A] にマッチする

・ ある文字が AA の A ならば、A[^A] にも [^A] にもマッチしない



これを図にすると下のようになります


▽ A[^A] と [^A] の関係図
A[^A] と [^A] の関係図


この図を見ると、ある文字にマッチさせるには、

A[^A] または [^A] にマッチさせればいいことが分かります


つまり、以下のようになります

(A[^A]|[^A])




そして、これを繰り返せば AA を含まない文字列となります

(A[^A]|[^A])*




最後に、

テキストの先頭と末尾の AA にマッチする表現を付け足し、

以下のようにすれば完成・・のはずですね

^AA(A[^A]|[^A])*AA$




では、試しに動かしてみましょう!

※ テキストエディタの OtbEdit では ^$ が行頭、行末にも
マッチするので、1行につき1つのテキストをテストします


▽ 「 ^AA(A[^A]|[^A])*AA$ 」 を動かした図
「 ^AA(A[^A]|[^A])*AA$ 」 を動かした図


図を見てみると、1、3、5、9、11行目は期待通りにマッチ
していますが、 2、6、10行目がマッチしていません


何故、この3行がマッチしないのかというと、

テキスト末尾にある AA のせいで、A[^A] がマッチしないのです


▽ 「 AA000AAA 」 の図
「 AA000AAA 」 の図


しかも、 A[^A]2文字 にマッチする表現なので、

1文字の A にはマッチ出来ません!


このように、文字列の否定表現では、

テキストの先頭、末尾の部分と競合して予期しない動作になる

ことが非常に多いので、必ずチェックしましょう!



では、これを直す作業を始めましょう

こういう誤作動を直す方法はケースバイケースなので

毎回違ってきますが、今回は下の図のように修正すればOKです


▽ 誤作動を直す図
誤作動を直す図


A[^A] でマッチ出来ないなら AA$ にマッチさせよう、

という発想です


では、 AA$ が AAA にもマッチするように修正します

AAA?$


A? を付けたので AA にも AAA にもマッチしますね!


これを適用した正規表現がこちらです

^AA(A[^A]|[^A])*AAA?$





では、改めてテストしてみましょう


▽ 「 ^AA(A[^A]|[^A])*AAA?$ 」 を動かした図
「 ^AA(A[^A]|[^A])*AAA?$ 」 を動かした図

2、 6、10行目もマッチしてますね! これで完成です★



今回は2文字の文字列の否定でしたが、否定する文字数が

多くなるととても複雑
になります


その場合は以下のような対策を検討しましょう

・ (?! ) を使えないかを確認しましょう
 (?! ) を使えれば記述がとてもシンプルになります

・ 否定の正規表現を使わずに済む方法がないかを確認しましょう
 プログラムでは ”肯定の正規表現がマッチしたらfalseにする” 等

・ 下記の自動生成 javascript で作成する


また、今回のような正規表現を作るには 状態機械 や
状態遷移図 、 オートマトン などの知識を身に付けると
取りこぼしの無い正確な正規表現が作れるように
なる・・のかも知れませんがよく分かりません
興味がある方は調べてみて下さい (^^;)



(?! ) に関連するページ

part29 - 先読み 否定 (?! )
part11 - いろいろな繰り返し (6)



○ 参考になるサイト

秀丸Q&A - 第IV部~テキスト編集を極める!!正規表現について
http://homepage2.nifty.com/jr-kun/hidemaru_qa/4_regulr.html
[2-2] 「文字列の否定」について” の項目がとても参考になります
※ 秀丸では (?! ) が使えます

Perl正規表現雑技
http://www.din.or.jp/~ohzaki/regex.htm#WithoutXY
xy を含まないものにマッチする正規表現” と
xyz を含まないものにマッチする正規表現” が参考になります

正規表現メモ
http://www.kt.rim.or.jp/~kbk/regex/regex.html
ある文字列を含まない正規表現” の項目に文字列の否定表現を
自動生成する javascript があります
( ”AA” の否定は出来ないようです )

教えてgoo - 文字列を含まないという正規表現は?
http://oshiete1.goo.ne.jp/qa4522181.html
プログラミングに関して有益なレスが付いています

ReplaceStrTool
http://1st.geocities.jp/neeetest/jane.html
( ) が何重にもなる複雑な正規表現を読みやすくするツールです
正規表現をコピーし、ツールの ”貼り付け” ボタンを押しましょう
フォームをダブルクリックするとフォームが最大化します

▽ ReplaceStrTool の階層表示機能の図
ReplaceStrTool の階層表示機能の図


前のページ    次のページ

テーマ : プログラミング
ジャンル : コンピュータ

コメントの投稿

非公開コメント

HOME


サイト内検索

QRコード
QRコード
Powered By FC2ブログ

今すぐブログを作ろう!
Powered By FC2ブログ