R语言正则表达式问题:如何精准提取导演名字(排除姓氏前缀)
问题:正确提取导演名字的正则表达式写法
背景与现有代码
我通过以下R代码获取了IMDB用户评分Top250电影的导演列表:
doc <- GET("https://www.imdb.com/chart/top") pagetext <- content(doc, as = "text") directors <- str_extract_all(pagetext, '(?<=")[^"]*(?=\\s\\(dir\\.\\))') dir_table <- sort(table(directors), decreasing = TRUE) dir_250 <- data.frame(dir_table)
将其转换为数据框后,添加了单名导演“Billy”用于测试:
dir_250$directors <- as.character(dir_250$directors) dir_250 <- rbind(dir_250, c("Billy", 1))
使用regex1成功提取了导演姓氏(Billy返回NA符合预期):
regex1 <- "((?<=\\s)(O\\'|[Dd]e(l)?(\\sla)?|[Vv](an|on))?\\s*[[:alpha:]]+\\-?[[:alpha:]]+)$" str_extract(dir_250$directors, regex1)
但使用regex2提取名字时,错误将Van、de这类姓氏前缀包含进去:
regex2 <- ".*(?=(\\s(O\\'|[Dd]e(l)?(\\sla)?|[Vv](an|on))?\\s*[[:alpha:]]+\\-?[[:alpha:]]+)$)" str_extract(dir_250$directors, regex2)
示例中,输入names <- c("Gus Van Sant", "George Roy Hill", "Paul Thomas"),regex2提取结果为[1] "Gus Van" "George Roy" "Paul",而预期结果是[1] "Gus" "George Roy" "Paul"。尝试多种修正均无效,求能正确提取名字的正则表达式写法。
解决方案
可以使用以下正则表达式来准确提取名字部分:
regex_fixed <- "^.*?(?=\\s(?:O'|[Dd]e(l)?(?:\\sla)?|[Vv](an|on))?\\s*[[:alpha:]]+\\-?[[:alpha:]]+$)"
测试示例:
names <- c("Gus Van Sant", "George Roy Hill", "Paul Thomas", "Billy") str_extract(names, regex_fixed)
输出结果:
[1] "Gus" "George Roy" "Paul" NA
修正说明
原regex2中的.*是贪婪匹配,会尽可能多的包含字符,导致把姓氏前缀(如Van)也纳入名字部分。改用.*?非贪婪匹配,让正则在遇到第一个符合姓氏前缀+姓氏的组合时就停止匹配,从而准确截断名字部分。同时用(?:...)将前缀部分改为非捕获组,不影响匹配逻辑的同时优化性能。
内容的提问来源于stack exchange,提问作者Gideon Parry
相关产品推荐
相关产品推荐

