4

正規表現にオプションパーツを実装する方法について質問があります。古き良きテキストアドベンチャー入力の解析から例を取り上げました。これは私の仕事をかなりよく強調しています。これが私が何を求めているかを示す例です:

var exp = /^([a-z]+)(?:\s([a-z0-9\s]+)\s(on|with)\s([a-z\s]+))?$/i;

var strings = [
    "look",
    "take key",
    "take the key",
    "put key on table",
    "put the key on the table",
    "open the wooden door with the small rusty key"
];

for (var i=0; i < strings.length;i++) {
    var match = exp.exec(strings[i]);

    if (match) {
        var verb = match[1];
        var directObject = match[2];
        var preposition = match[3];
        var indirectObject = match[4];

        console.log("String: " + strings[i]);
        console.log("  Verb: " + verb);
        console.log("  Direct object: " + directObject);
        console.log("  Preposition: " + preposition);
        console.log("  Indirect object: " + indirectObject);    
    } else {
        console.log("String is not a match: " + strings[i]);
    }
    console.log(match);
}

私の正規表現は、最初と最後の3つの文字列に対して機能します。

他のメソッド(.split()など)を使用して正しい結果を取得する方法を知っています。これは正規表現を学習する試みなので、これを行う別の方法を探していません:-)

オプションの非キャプチャグループをさらに追加しようとしましたが、機能させることができませんでした。

var exp = /^([a-z]+)(?:\s([a-z0-9\s]+)(?:\s(on|with)\s([a-z\s]+))?)?$/i;

これは最初の3つの文字列では機能しますが、最後の3つの文字列では機能しません。

だから私が欲しいのは:最初の単語、指定された単語(「on」のような)までのいくつかの文字、文字列の終わりまでのいくつかの文字

トリッキーな部分は、さまざまなバリエーションです。

できますか?

実用的なソリューション:

exp = /^([a-z]+)(?:\s((?:(?!\s(?:on|with)).)*)(?:\s(on|with)\s(.*))?)?$/i;
4

1 に答える 1

2

おそらくこのようないくつかの正規表現:

var exp = /^([a-z]+)(?:(?:(?!\s(?:on|with))(\s[a-z0-9]+))+(?:\s(?:on|with)(\s[a-z0-9]+)+)?)?$/i;

グループ\s[a-z0-9]+は、スペースが前に付いた単語をキャプチャします。

(?!\s(?:on|with))この単語が「on」または「with」になるのを避けます。

したがって(?:(?!\s(?:on|with))(\s[a-z0-9]+))+、「on」または「with」の前の単語のリストです。

ここでテストできます。

于 2012-12-03T14:31:20.477 に答える