我有一个问题,想要实现正则表达式中的可选部分。我拿了一个解析旧文本冒险游戏输入的例子来说明我的任务。这个例子很好地展示了我的需求。以下是一个例子来展示我的目的:
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);
}
我的正则表达式对于第一个和最后三个字符串有效。
我知道如何使用其他方法(比如.split())获得正确的结果。这是尝试学习正则表达式,因此我不想寻找另一种替代方法来完成这个任务 :-)
我已经尝试添加更多可选的非捕获组,但是我无法使其工作:
var exp = /^([a-z]+)(?:\s([a-z0-9\s]+)(?:\s(on|with)\s([a-z\s]+))?)?$/i;
这对前三个字符串有效,但对后三个无效。
所以我想要的是: 第一个单词,一些字符直到指定的单词(如 "on"),一些字符直到字符串结尾
棘手的部分是不同的变体。
可以完成吗?
有效解决方案:
exp = /^([a-z]+)(?:\s((?:(?!\s(?:on|with)).)*)(?:\s(on|with)\s(.*))?)?$/i;
?:
只是生成一个不匹配的组,与可选项无关。可选项组在末尾有一个?
,或者被量化为明确的可选项,如{0,1}
。然而,使用太多的可选项组是没有意义的,因为您需要检查每个匹配组是否存在。 - dognose(?:这部分是可选的)?
- Thomas