提取可能多次出现或根本不出现的字符串元素

law*_*yeR 6 substring r strsplit regex-lookarounds

从URL的字符向量开始.我们的目标是与公司的唯一名称最终,只意味着一列"test","example""sample"在下面的例子.

urls <- c("http://grand.test.com/", "https://example.com/", 
          "http://.big.time.sample.com/")
Run Code Online (Sandbox Code Playgroud)

删除".com"可能跟随它的任何内容并保留第一部分:

urls <- sapply(strsplit(urls, split="(?<=.)(?=\\.com)", perl=T), "[", 1) 

urls
# [1] "http://grand.test"    "https://example"      "http://.big.time.sample"
Run Code Online (Sandbox Code Playgroud)

我的下一步是使用链式调用删除http://https://部分gsub():

urls <- gsub("^http://", "",  gsub("^https://", "", urls))

urls
# [1] "grand.test"       "example"          ".big.time.sample"
Run Code Online (Sandbox Code Playgroud)

但这是我需要帮助的地方.如何在第一个和第三个网址字符串中处理公司名称之前的多个句点(点)?例如,下面的调用返回第二个字符串的NA,因为该"example"字符串没有剩余句点.或者,如果我只保留第一部分,我会丢失公司名称.

urls  <- sapply(strsplit(urls, split = "\\."), "[", 2)
urls
# [1] "test" NA     "big"

urls  <- sapply(strsplit(urls, split = "\\."), "[", 1)
urls
# [1] "grand"   "example" ""  
Run Code Online (Sandbox Code Playgroud)

也许是一个ifelse()计算剩余句点数的调用,如果有多个句点,则仅使用strsplit?另请注意,公司名称前可能有两个或更多个期间.我不知道如何做外观,这可能解决我的问题.但事实并非如此

strsplit(urls, split="(?=\\.)", perl=T)
Run Code Online (Sandbox Code Playgroud)

谢谢你的任何建议.

Jos*_*ien 3

这是一种比其他方法更容易理解和概括的方法:

pat = "(.*?)(\\w+)(\\.com.*)"
gsub(pat, "\\2", urls)
Run Code Online (Sandbox Code Playgroud)

它的工作原理是将每个字符串分成三个捕获组,这些捕获组一起匹配整个字符串,然后替换回(2)您想要的捕获组。

pat = "(.*?)(\\w+)(\\.com.*)"
#        ^    ^       ^
#        |    |       |
#       (1)  (2)     (3)  
Run Code Online (Sandbox Code Playgroud)

编辑(添加?修饰符的解释)

请注意,捕获组(1)需要包含“ungreedy”或“minimal”量词?有时也称为“lazy”或“reluctant”)。它本质上告诉正则表达式引擎匹配尽可能多的字符......而不用完任何可能成为以下捕获组一部分的字符(2)

如果没有尾随?,重复量词默认是贪婪的;在这种情况下,贪婪的捕获组 ,(.*)由于它匹配任意数量的任何类型的字符,因此会“吃掉”字符串中的所有字符,而不会为其他两个捕获组留下任何字符 - 这不是我们想要的行为!