正規表現で「0回以上に一致」

正規表現については、そのとき必要なことだけをとりあえず付け焼刃で、というやり方ばっかりしててあんまり格闘したことなかったなあと思ったのでこのエントリ。
といってもやっぱり必要な分だけなのですが。


ダイス振る時に数値を省略すること、よくありますので、それをも受け付けるようにしてみたいと思います。

ベースになるスクリプト

function event::onChannelText(prefix, channel, text)
{
    
    //ベタ出力
    //send(channel, prefix.nick + ':' + text );

    if (text.match(/!\d+R\d+/i)){

        //該当文字列を配列matchedTextに格納
        var matchedText = text.match(/!(\d+)R(\d+)/i);
        
        //配列の中身を出力
        for (var i = 0; i < matchedText.length; i++){
            send(channel, '[' + i + '] = ' + matchedText[i] );
        }

    }
}

以前もあげた奴です。これを改造しながら今回のお題を一つ。

これを実行した結果は以下の通り。

21:34 (ten-you) !1r10
21:34 (ten-you) [0] = !1r10
21:34 (ten-you) [1] = 1
21:34 (ten-you) [2] = 10

21:34 (ten-you) !r

ということで↓

お題

!以降、一部の数値を省略しても反応する正規表現をつくる

ろあだいすは「#d100」「#3r」のような入力をした場合、自動的に「1d100」「#3r10」と解釈して反応するのです。
これをまねしたい。

「+」を「*」に。

単純に。
正規表現において「+」は直前の文字の1回以上に一致、「*」は0回以上に一致なので。
これで実行した結果が以下に↓


●今までの入力フォーマットそのまま。

21:36 (ten-you) !1r10
21:36 (ten-you) [0] = !1r10
21:36 (ten-you) [1] = 1
21:36 (ten-you) [2] = 10


●クリティカル値を省略。

21:38 (ten-you) !1r
21:38 (ten-you) [0] = !1r
21:38 (ten-you) [1] = 1
21:38 (ten-you) [2] =


●ダイス数を省略。

21:38 (ten-you) !r10
21:38 (ten-you) [0] = !r10
21:38 (ten-you) [1] =
21:38 (ten-you) [2] = 10


●全部省略。

21:38 (ten-you) !r
21:38 (ten-you) [0] = !r
21:38 (ten-you) [1] =
21:38 (ten-you) [2] =

「0回以上」って、こういうふうに反応するんですね。
私はてっきり、2つの数字のうち1つ目を省略したら、2つ目の数字が1つ目の数字として認識されるんだと思ってました。こんなふうに↓

21:38 (ten-you) !r10
21:38 (ten-you) [0] = !r10
21:38 (ten-you) [1] = 10

もうちょっと条件を増やしてみる

ではさらに。「いぬい」でやりたかった「途中経過の表示の有無と表示する場合の繰り返し回数の指定」のために、「@数字」をも拾うようにしてみます。
スクリプトを起動する発言に「@数字」がついてたら、数字回数分だけ繰り返しするように、ということ。

「@*\d*」を足してみた

ええと、正確には「@*\d*」と「@*(\d*)」。
スクリプトはこんな感じに。

function event::onChannelText(prefix, channel, text)
{
    
    //ベタ出力
    //send(channel, prefix.nick + ':' + text );

    if (text.match(/!\d*R\d*@*\d*/i)){

        //該当文字列を配列matchedTextに格納
        var matchedText = text.match(/!(\d*)R(\d*)@*(\d*)/i);
        
        //配列の中身を出力
        for (var i = 0; i < matchedText.length; i++){
            send(channel, '[' + i + '] = ' + matchedText[i] );
        }

    }
}

そしてこの結果は以下に↓

●今までの入力フォーマットそのまま。
(だから@以下は省略)

21:48 (ten-you) !1r10
21:48 (ten-you) [0] = !1r10
21:48 (ten-you) [1] = 1
21:48 (ten-you) [2] = 10
21:48 (ten-you) [3] =


●数値が入れられるところは全部入力。

21:48 (ten-you) !1r10@3
21:48 (ten-you) [0] = !1r10@3
21:48 (ten-you) [1] = 1
21:48 (ten-you) [2] = 10
21:48 (ten-you) [3] = 3

……なんか、一発で思い通りの結果が出てかえって不安になるんですが。


不安になったんでいろいろ意地悪入力もしてみました。


●@まで入れておいてその後ろの数字は省略。

21:50 (ten-you) !1r10@
21:50 (ten-you) [0] = !1r10@
21:50 (ten-you) [1] = 1
21:50 (ten-you) [2] = 10
21:50 (ten-you) [3] =


●クリティカル値だけを省略。

21:50 (ten-you) !1r@3
21:50 (ten-you) [0] = !1r@3
21:50 (ten-you) [1] = 1
21:50 (ten-you) [2] =
21:50 (ten-you) [3] = 3


●ダイス数だけ省略。

21:50 (ten-you) !r10@3
21:50 (ten-you) [0] = !r10@3
21:50 (ten-you) [1] =
21:50 (ten-you) [2] = 10
21:50 (ten-you) [3] = 3


●ダイス数とクリティカル値を省略して繰り返し回数だけ入力。

21:50 (ten-you) !r@3
21:50 (ten-you) [0] = !r@3
21:50 (ten-you) [1] =
21:50 (ten-you) [2] =
21:50 (ten-you) [3] = 3


●数値全部省略。

21:50 (ten-you) !r@
21:50 (ten-you) [0] = !r@
21:50 (ten-you) [1] =
21:50 (ten-you) [2] =
21:50 (ten-you) [3] =

太字が自分入力。その下が返ってきた結果です。……うーん。理想どおりだ。ほんとにこれでいいのか?

余談。

ところで正規表現はいわゆる『方言』が多いそうです。ということは今格闘しても、他の言語とかではやっぱり勉強しなおしなんだろうなあ。