3

我正在尝试使用正则表达式来标记我从 IMDB 的文本界面下载的电影标题。

RE 的简化版本将演示我遇到的问题。这是一个示例标题:

"'Allo 'Allo!" (1982)
"A film in production" (????)

我可以像这样匹配它:

re=/(\".*\")\s(\(.{4}\));

然后我可以使用子表达式在 javascript 中标记电影,就像这样:

titleParts = rawTitle.match(re);
console.log('title %s', titleParts[0]);

但后来我发现了这样的电影片名:

Unquoted film title  (2012)

因为标题周围没有引号,所以我不能再将元素匹配到子表达式中:

re=/((\"){0,1}.*(\"){0,1})\s(\(.{4}\));

请注意,我通过指定引号是可选的来更改原始 RE。但是现在发生的是整个字符串匹配第一个 subExpression。

我该如何解决这个问题?

4

4 回答 4

3

您的标题实际上在 index 1not上可用0

console.log('title %s', titleParts[1]); // "title Unquoted film title "

您不应该在标题周围捕获引号和空格。这会导致标题显示不一致:有时引用,有时不引用;或者,将需要不必要且应避免的字符串操作。

如果您的标题字符串始终包含该(year)部分并假设 IMDB 将在电影标题中使用单引号(如您的示例中),您的正则表达式可以简化为

"?(.*?)"?\s+\((.{4})\)

这里有一些 JavaScript 可以一致地打印带有引号的标题:

var titles = [
    "\"'Allo 'Allo!\" (1982)",
    "\"A film in production\" (????)",
    "Hachi: A Dog's Tale (2009)"
];

var re = /"?(.*?)"?\s+\((.{4})\)/;

for each ( var t in titles ) {
    var titleParts = t.match(re);
    console.log('Title: "%s" ; Year: %s', titleParts[1], titleParts[2]);
}

输出:

Title: "'Allo 'Allo!" ; Year: 1982
Title: "A film in production" ; Year: ????
Title: "Hachi: A Dog's Tale" ; Year: 2009
于 2013-09-08T07:37:55.113 回答
0

我在正则表达式^("?[\w\s!']+"?)\s\((.{4})\)$中尝试了这个表达式,它适用于你的所有情况。

于 2013-09-08T06:44:26.127 回答
0

您永远不应该将正则表达式用于强大的标记化解决方案。标记化已经够难了,我保证你会遇到更多你还没有遇到的边缘情况。

改用这个:

https://npmjs.org/package/tokenizer

于 2013-09-08T06:53:31.003 回答
0

你的问题是贪婪的量词.*,它总是匹配(空字符串也是)。要么你使用更具体的东西来捕捉标题,比如 prasanth 的建议[\w\s!']+,但也许你需要更多的标点符号,或者你使用所有格量词.+?(我更喜欢+这里*,因为你想抓住一些东西)。所以你的正则表达式是:

re=/(\"?.+?\"?)\s(\(.{4}\));
于 2013-09-08T07:38:48.140 回答