从关闭的this question中,运算符(operator)询问如何从字符串中提取排名,首位,中间和最后一位
x <- c("Marshall Robert Forsyth", "Deputy Sheriff John A. Gooch",
"Constable Darius Quimby", "High Sheriff John Caldwell Cook")
# rank first middle last
# Marshall Robert Forsyth "Marshall" "Robert" "" "Forsyth"
# Deputy Sheriff John A. Gooch "Deputy Sheriff" "John" "A." "Gooch"
# Constable Darius Quimby "Constable" "Darius" "" "Quimby"
# High Sheriff John Caldwell. Cook "High Sheriff" "John" "Caldwell" "Cook"
我想出了这个方法,只有在中间名包含句点的情况下,它才有效。否则,排名模式会从行开始处捕获尽可能多的内容。
pat <- '(?i)(?<rank>[a-z ]+)\\s(?<first>[a-z]+)\\s(?:(?<middle>[a-z.]+)\\s)?(?<last>[a-z]+)'
f <- function(x, pattern) {
m <- gregexpr(pattern, x, perl = TRUE)[[1]]
s <- attr(m, "capture.start")
l <- attr(m, "capture.length")
n <- attr(m, "capture.names")
setNames(mapply('substr', x, s, s + l - 1L), n)
}
do.call('rbind', Map(f, x, pat))
# rank first middle last
# Marshall Robert Forsyth "Marshall" "Robert" "" "Forsyth"
# Deputy Sheriff John A. Gooch "Deputy Sheriff" "John" "A." "Gooch"
# Constable Darius Quimby "Constable" "Darius" "" "Quimby"
# High Sheriff John Caldwell Cook "High Sheriff John" "Caldwell" "" "Cook"
因此,如果中间名没有给出或包含句点,这将起作用
x <- c("Marshall Robert Forsyth", "Deputy Sheriff John A. Gooch",
"Constable Darius Quimby", "High Sheriff John Caldwell. Cook")
do.call('rbind', Map(f, x, pat))
所以我的问题是,有没有一种方法可以从字符串的末尾开始对匹配进行优先级排序,以使该模式匹配最后,中间,第一个,然后将所有其他内容排在排名之前。
我能做到这一点而无需反转字符串或类似的东西吗?另外,也许有更好的模式,因为我对正则表达式不太满意。
相关-[1] [2]-我认为这些方法不起作用,因为建议了另一种模式而不是回答问题。同样,在此示例中,等级中的单词数是任意的,并且与等级匹配的模式也适用于名字。
最佳答案
我们不能从头开始匹配,在我知道的任何正则表达式系统中都没有针对它的修饰符。但是我们可以检查到底有多少个单词,并限制我们的贪婪:)。下面的正则表达式正在执行此操作。
这将满足您的要求:
^(?<rank>(?:(?:[ \t]|^)[a-z]+)+?)(?!(?:[ \t][a-z.]+){4,}$)[ \t](?<first>[a-z]+)[ \t](?:(?<middle>[a-z.]+)[ \t])?(?<last>[a-z]+)$
Live preview in regex101.com
还有一个异常(exception):
当您的排名具有“第一”,“最后”和超过1个单词时,排名的一部分将成为“名字”。
为了解决这个问题,您必须定义一个等级前缀列表,这意味着后面肯定还有另一个单词并以贪婪的方式捕获它。
例如:副手,高级。
关于r - 从字符串末尾开始匹配,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40575516/