为什么模式适用于 str_extract_all 但不适用于 strsplit 或 str_subset?

Why a pattern works for str_extract_all but does not work for strsplit nor str_subset?

这是我的数据,一个字符串:

data <- "Mr. NAME. Content1.Mrs. NAMEE. Content2.Ms. NAME ABCD. Content3."

我通过以下语法获得名称向量:

name <- unlist(str_extract_all( text, "Mr\.\s[:upper:]{1,20}\s?[:upper:]{1,20}\.|Ms\.\s[:upper:]{1,20}\s?[:upper:]{1,20}\.|Mrs\.\s[:upper:]{1,20}\s?[:upper:]{1,20}\." ))

我得到了我想要的:

name [1] "Mr. BOOKER." "Mr. COMER." "Mr. BAIRD." "Mrs. KIRKPATRICK."
[5] "Ms. CORTEZ MASTO." "Ms. ROSEN." "Mrs. HAYES." "Ms. SHALALA."
[9] "Mr. DEUTCH." "Mr. KENNEDY." "Mr. KRISHNAMOORTHI." "Mr. SOTO."
[13] "Mr. SOTO." "Mrs. DEMINGS." "Mr. SOTO." "Mr. CICILLINE."
[17] "Mr. SOTO." "Ms. WASSERMAN SCHULTZ." "Mr. SOTO." "Ms. WASSERMAN SCHULTZ."

如何获取名称之间内容的向量。我想要这样的矢量:

"Content1."   "Content2."    "Content3."

我试过str_subset和strsplit来获取我在str_extract函数中定义的模式之间的内容,一次又一次失败......

获得所需结果的一种简单方法是使用 string_replace_all 将正则表达式折叠为一个标记,然后按该标记拆分:

#Dropping many alternative patterns, 
pattern = "Mr\.\s[:upper:]{1,20}\s?[:upper:]{1,20}\." #etc etc
name <- unlist(stringr::str_replace_all( data, pattern, "xyx"))
stringr::str_split(name, "xyx")

产量

""           " Content1." " Content2." " Content3."

您真的可以在 stringr::str_split 中使用您的正则表达式。但是,将备选方案压缩为

是有意义的
pattern <- "\bM(?:rs?|s)\.\s\p{Lu}{1,20}\s?\p{Lu}{1,20}\."

MsMrMrs 可以加入 M(?:rs?|s) 模式(M,然后是 r 和可选的 ss).

现在,您可以将此模式与 stringr::str_split 一起使用:

pattern <- "\bM(?:rs?|s)\.\s\p{Lu}{1,20}\s?\p{Lu}{1,20}\."
library(stringr)
str_split(data,pattern)
# => [[1]]
#    [1] ""           " Content1." " Content2." " Content3."

为什么开头是空字符串?它在那里是因为你在字符串的开头有一个匹配项。拆分时,将匹配的文本从字符序列中移除,并将前后文本放入单独的项中。当匹配开始时,第一项是空字符串。当匹配在字符串的末尾,或者有连续的匹配时,也会发生同样的情况。

如果您不想在输出中包含空项,只需将它们删除即可:

pattern <- "\bM(?:rs?|s)\.\s\p{Lu}{1,20}\s?\p{Lu}{1,20}\."
library(stringr)
result <- str_split(data,pattern)
lapply(result, function(x) x[x!=""])
# => [[1]]
#    [1] " Content1." " Content2." " Content3."