取以下字符向量x
x <- c("1 Date in the form", "2 Number of game",
"3 Day of week", "4-5 Visiting team and league")
我想要的结果是以下向量,其中每个字符串中的第一个大写单词,并且如果字符串包含 -
,也是最后一句话。
[1] "Date" "Number" "Day" "Visiting" "league"
所以而不是这样做
unlist(sapply(strsplit(x, "[[:blank:]]+|, "), function(y){
if(grepl("[-]", y[1])) c(y[2], tail(y,1)) else y[2]
}))
为了得到结果,我想我可以尝试将其缩短为正则表达式。结果几乎与 sub
中的这个正则表达式“相反” 。我已经尝试了各种方法来获得相反的结果,使用不同品种的[^A-Za-z]+
等等,但尚未成功。
> sub("[A-Z][a-z]+", "", x)
[1] "1 in the form" "2 of game"
[3] "3 of week" "4-5 team and league"
所以我想这是一个由两部分组成的问题。
与
sub()
或gsub()
,如何返回"[A-Z][a-z]+"
的相反值?如何将正则表达式编写为“匹配第一个大写单词,如果字符串包含
-
,则还匹配最后一个单词。”? p>
最佳答案
以下是一些建议:
要使用
sub
提取第一个大写单词,您可以使用sub(".*\\b([A-Z].*?)\\b.*", "\\1", x) #[1] "Date" "Number" "Day" "Visiting"
其中
\\b
表示单词边界。您还可以使用一个
sub
命令提取所有单词,但请注意,您必须应用额外的步骤,因为sub
返回的向量长度与输入向量x
的长度相同。以下正则表达式使用前瞻 (
(?=.*-)
) 来测试字符串中是否存在-
。如果是这种情况,则提取两个词。如果不存在,则应用逻辑 or (|
) 之后的正则表达式,并仅返回第一个大写单词。res <- sub("(?:(?=.*-).*\\b([A-Z].*?\\b ).*\\b(.+)$)|(?:.*\\b([A-Z].*?)\\b.*)", "\\1\\2\\3", x, perl = TRUE) # [1] "Date" "Number" "Day" "Visiting league"
为了分隔同一字符串中的多个单词,还需要一个额外的步骤:
unlist(strsplit(res, " ", fixed = TRUE)) # [1] "Date" "Number" "Day" "Visiting" "league"
关于regex - "opposite"结果的正则表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24670038/