場外乱闘~正規表現のお話~


前置き


こんにちは、Bot作成に頭を悩ましているリトマスである。
今私はより良いBot作成を目指していて奮闘中である。その過程でさまざまな障害にぶつかっているわけだが
Botにリプライをさせるところまで発展した時、必ず向き合わなければならないものがあった。
それは正規表現である。
ネットで調べてみると正規表現の記事があるが、Bot作成に関わる形で紹介しているサイトはあまりない。
そこで今回は幾らか例を挙げつつ、Bot作成でよく使うであろう使い方を紹介したいと思う。
戦極姫、武田信玄の記事ではない?諸事情により23日辺りに記事を作る予定である。

単語と文章の検知


まず最初に 例えば相手の「ありがとう」を検知して「どういたしまして」と返したいときどうするか?
相手は「ありがとう」、「有難う」、「アリガトウ」と言ってくるかもしれない。 そんな時に用いるメタ文字の|である。

例1
ありがとう|アリガトウ|有難う 

この場合上記の3つの単語に反応を返せる。
例えば「ありがとう」はもちろん「ありがとうございます」、「アリガトウございます」にも検知して応答できる。
これで複数の単語から拾って応答するには成功するが 中には単語だけで検知すると意図しなかった応答をしてしまう場合がある。
例えば相手が徹夜したであろう言葉を検知し、「大丈夫か?」と相手を心配することを想定し、 例2のような正規表現をする。

例2
徹夜|夜更かし

しかしここで問題が起こる。

「つらかった。徹夜したんだよ」→「大丈夫か?」
「やっぱり徹夜には魔剤だね」→「大丈夫か?」
「夜更かしは辛いよね」→「大丈夫か?」

上記のうちどれにも反応してしまうのだ。 このままだと2番目と3番目のパターンにも返してしまい不自然である。 (2つ目は自然?)
そんな時には()を使い文字列をグループにまとめるといい。

例3
(徹夜|夜更かし)(した|してしまった)

この場合「徹夜した」、「夜更かしした」、「夜更かししてしまった」を検知できる。
また「徹夜」という単語は「徹夜をした」、「徹夜した」という風に表現できる。 このように言葉には、ほとんど同じ意味だが間に特定の文字を挟む、挟まないものもある。 その時は?(半角の)を使うといい。

例4
(徹夜|夜更かし)(を)?(した|してしまった)

「夜更かしをした」、「徹夜をしてしまった」にも反応できるようになった。 また()の中に()を入れることもできてこんな使い方もできる。

例5
(リンゴ|りんご)((が|は)好き|(を|だけ)好む)

「リンゴが好き」「りんごだけ好む」、「リンゴを好む」も検知できる。

広い範囲の文章を検知したい場合


Botに狭い範囲のワードのみを検知させるような仕組みにすると、寂しいのである。 何が言いたいかというと「好きでも」いろんな尺度があり

リンゴがそれなりに好き
ラーメンがかなり好き
ゴジラが素晴らしく好き
武田信玄がとてつもなく好き
YouがVeryで好き

と幾らでもある。例5のままでは「が」と「好き」の合間に何か表現を挟む、
あるいは主語をリンゴ以外の単語にするだけで反応しない。
それぞれの様々な「がとても好き」、「がかなり好き」など作りまくればいいのではないかと思うが、全て書くようでは製作者が死んでしまう。
手軽に広い範囲に反応できる方法はないか?
そこで*と.を併用をする。

例6
が.*好き

反応例として「ラーメンがかなり好き」、「武田信玄がとてつもなく好き」、「睡眠が大好き」を挙げとく。
結果的にいろんな好きに反応するようになり、 広い範囲を検知できるようになった。
しかし何でも反応してしまうため、応答次第や場合によって悲惨な事になる。 例えば検知したワードに対して「私もそれが好き」と応答する時。

「淫夢がすごく好き」→「私もそれが好き」

・・・・・・・・・これはどうだろうか?正直困惑する。
てかそんなあほくさいリプすんな
これの解決策は後に紹介する後読み否定グループを読んでいただきたい。

先読み否定グループを用いた疑問文の検知


実は例3ではまだ致命的なミスをしている。

「徹夜をした?」→「大丈夫?」
「徹夜したの?」→「大丈夫?」

質問を質問で返しているのである。これは大変失礼なことであり、またこれに対する応答も不自然である。
そこで末尾に?がついてた場合何か質問していると察し、反応しないようにする。
そのため先読み否定グループを使用することで問題を解決する。

例7
(徹夜|夜更かし)(を)?(した|してしまった)(?!(?))

「徹夜をした」、「徹夜してしまった」等には反応するが「徹夜したの?」等の疑問形はスルーできるようになった。

後読み否定グループを用いた淫夢の排除


例6を改良して淫夢の排除を試みたい。今回は淫夢が好き的な事を言ったらスルーするようにする。
そのために後読み否定グループを用いる。

例8
(?<!淫夢)が.*好き

これで淫夢は無視できるようになった。|と併用することで、無視する言葉を増やすこともできる。

例9
(?<!淫夢|野獣)が.*好き

上記では淫夢、野獣の排除ができる。 悪いけどホモはNG

終わりに


プログラム上でできたBotといえども、 今回示した正規表現を用いるだけで、結構柔軟な反応をしてくれるようになる。
しかし動かしていくうちにまた新たな問題が生じるであろう。 ユーザーは制作者が意図した動きをしてくれるとは限らないのである。
それも正規表現を駆使してでは解決できない問題かもしれない。 その時には別の機会に紹介していきたいと思う。
Botの方は年末には再び公開する予定である。

お世話になったサイト


http://www.gimite.net/help/devas-ja/all_regex.html
http://www.gimite.net/help/devas-ja/100regex.html
http://www.megasoft.co.jp/mifes/seiki/meta.html