シーンインした時に侵蝕率を計算するスクリプト(2)
(1)からの続きです。
……実は遅々として進んでおりません。ぐるぐるしてます。
理由はmatch()。
「#シーンイン+(半画数字)」という文字列を拾って数字だけ抜き出す
(1)の結果を踏まえて、発言から「#シーンイン+(半画数字)」という文字列を拾って数字だけ抜き出すスクリプトを書いてみました。
function event::onChannelText(prefix, channel, text) { if (text.match(/#シーンイン\+[0-9]+/)) { var matchedText = text.match(/#シーンイン\+[0-9]+/); send(channel, matchedText); send(channel, matchedText.match(/[0-9]+/)); } }
同じ判定を繰り返してるのがスマートじゃないですが、見逃してください。
これの実行結果は以下に。
00:34 (ten-you) あああああああああ#シーンイン+46あああああああああああああああ
00:34 (ten-you) #シーンイン+46
1行目が参加者の発言、2行目がスクリプトの実行結果です。
……「send(channel, matchedText.match(/[0-9]+/));」が実行されてませんよ?
sendコマンドは2回連続して送信しちゃいけないんでしょうか?
send(channel, matchedText + ' ' + matchedText.match(/\d+/));
と、書き換えて実行してみましたが、今度は
00:34 (ten-you) あああああああああ#シーンイン+46あああああああああああああああ
と、無反応。つまり余計ひどい状態に。
うーん?
以降、あれこれ手を変え品を変え、どうにか実行できるよう頑張ってみたのですが、どうにもなりませんでした。
いろいろやってみてわかったのは一つ。
match()で抽出した結果にさらにmatch()すると失敗する。
しかしmatch()で返ってきてるのはString型、文字列のはずです。ううむ?
というところでどうにもつまって、師匠的存在wに質問してみました。
で、JavaScriptでの正規表現の扱いはよく知らないが、と前置きした上で言われたこと。
「match()の戻り値は配列じゃないの?」
今まで使ったことのある正規表現のライブラリはたいてい戻り値が配列になってたとのことです。
たしかに、配列に対して文字列の検索かけてもいかにもダメそうです。なんとなく。
ここで、JavaScript リファレンス - JavaScript | MDNからmatch()について調べてみました。
すると、
詳細
正規表現が g フラグを含んでいない場合、regexp.exec(string) と同じ結果を返します。
正規表現が g フラグを含んでいる場合、マッチのすべてを含む 配列 (Array) を返します。
String.prototype.match() - JavaScript | MDN
強調装飾は私です。
ちなみに。
単に、マッチが真か偽かを調べたい場合は、test メソッド か、String.search メソッドを使ってください。
RegExp.prototype.exec() - JavaScript | MDN
とのことなのですが……これはLimeChatでは動きませんでした。理由はよく分かりませんが、ダメらしい。サンプルで使ってなかったわけです。
というわけで、こんな感じに書き換えました。
function event::onChannelText(prefix, channel, text) { if (text.match(/#シーンイン\+[0-9]+/)) { //配列arrMatchedTextを定義。初期値としてマッチングしたデータを格納 var arrMatchedText = text.match(/#シーンイン\+[0-9]+/); //配列arrMatchedTextの1つめに格納されたデータを表示 send(channel, arrMatchedText[0]); //配列arrMatchedTextの0番目に格納されたデータにマッチングして表示 send(channel, arrMatchedText[0].match(/[0-9]+/)); } }
実行結果は以下のとおり。
11:13 (ten-you) #シーンイン+50あああああああああああああ
11:13 (ten-you) #シーンイン+50
11:13 (ten-you) 50
できたー!!
戻り値が配列だと分かったついでに、(1)で結果から勘違いしてたスクリプトを書き直してみました。これです↓
function event::onChannelText(prefix, channel, text) { var matchedText = 'aaaaabc#シーンイン+11aaaaaaa#シーンイン+22cccc#シーンイン+33cc'; if (text.match(/#/)) { send(channel, matchedText.match(/#シーンイン\+[0-9]+/)); } }
これを、以下のように書き換えて実行してみました。
function event::onChannelText(prefix, channel, text) { var testText = 'aaaaabc#シーンイン+11aaaaaaa#シーンイン+22cccc#シーンイン+33cc'; if (text.match(/#/)) { var arrMatchedText = testText.match(/#シーンイン\+[0-9]+/) send(channel, '[0]=' + arrMatchedText[0]); send(channel, '[1]=' + arrMatchedText[1]); send(channel, '[2]=' + arrMatchedText[2]); } }
意図したとおりになるのなら、
[0]=#シーンイン+11
[1]=#シーンイン+22
[2]=#シーンイン+33
と出力されるはず!
で、実行結果↓
20:17 (ten-you) #
20:17 (ten-you) [0]=#シーンイン+11
20:17 (ten-you) [1]=undefined
20:17 (ten-you) [2]=undefined
……おや?
追記
Array - JavaScript | MDNにmatch()の結果について記述がありました。
マッチ結果を利用した配列の生成
正規表現と文字列との間のマッチ結果は、配列を生成することがあります。この配列は、そのマッチについての情報を持つプロパティと要素を持ちます。 RegExp.exec、String.match と String.replace の戻り値は配列です。これらのプロパティと要素を説明する助けとして、次の例を見て、そして下の表を参照してください。
(中略)Array - JavaScript | MDN
プロパティ/要素 説明 例 [0] 読み取り専用の要素で、最後に一致した文字列を指す。 dbBd [1], ...[n] 読み取り専用の要素で、もし正規表現が丸括弧で囲まれたサブ文字列を含むなら、それらにマッチした文字列を指す。可能な丸括弧で囲まれたサブ文字列の数は制限されていません。 [1]: bB [2]: d
強調は自分です。なるほど。だから思った結果にならなかったんですねー。
さらに追記(08-12-02)
スクリプトの一部を書き換えました。理由は後日。