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

R 提取可能多次出现或根本不出现的字符串元素,r,substring,regex-lookarounds,strsplit,R,Substring,Regex Lookarounds,Strsplit,从URL的字符向量开始。目标是以公司名称结束,这意味着在下面的示例中,列中只包含“test”、“example”和“sample” urls <- c("http://grand.test.com/", "https://example.com/", "http://.big.time.sample.com/") 我的下一步是使用链式gsub()调用删除http://和https://部分: urls <- gsub("^http://", "", gsub

从URL的字符向量开始。目标是以公司名称结束,这意味着在下面的示例中,列中只包含
“test”
“example”
“sample”

urls <- c("http://grand.test.com/", "https://example.com/", 
          "http://.big.time.sample.com/")
我的下一步是使用链式
gsub()
调用删除
http://
https://
部分:

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

urls
# [1] "grand.test"       "example"          ".big.time.sample"
可能是一个
ifelse()
调用,它计算剩余的周期数,并且仅在存在多个周期时使用strsplit?还请注意,公司名称前可能有两个或多个句点。我不知道如何环顾四周,这可能会解决我的问题。但事实并非如此

strsplit(urls, split="(?=\\.)", perl=T)

谢谢您的建议。

我认为应该有更简单的建议,但这是可行的:

 sub('.*[.]','',sub('https?:[/]+[.]?(.*)[.]com[/]','\\1',urls))
 [1] "test"    "example" "sample" 

其中“url”是你第一个url的矢量。

我认为有一种方法可以把“.com”前面的单词提取出来,但可能会给出一个想法

sub(".com", "", regmatches(urls, gregexpr("(\\w+).com", urls)))

使用strsplit可能也值得一试:

sapply(strsplit(urls,"/|\\."),function(x) tail(x,2)[1])
#[1] "test"    "example" "sample"

您可以使用
stringr::word()
,以及
basename()

basename()
在处理URL时非常方便

> library(stringr)
> word(basename(urls), start = -2, sep = "\\.")
# [1] "test"    "example" "sample"  
basename(URL)

[1] "grand.test.com"       "example.com"          ".big.time.sample.com"

然后,在
word()
函数中,我们从末尾取第二个单词(
start=-2
),因为分隔符是
sep=“\\\”
)。

因为您从来没有足够的正则表达式选项,这里是使用函数的


如果只需要返回值的简单向量,可以
unlist()
结果。该模式的思想是抓住“.com”前面不是点或“/”的所有内容。

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

pat = "(.*?)(\\w+)(\\.com.*)"
gsub(pat, "\\2", urls)
它的工作原理是将每个字符串分成三个捕获组,这些捕获组一起匹配整个字符串,然后替换回您想要的捕获组
(2)

pat = "(.*?)(\\w+)(\\.com.*)"
#        ^    ^       ^
#        |    |       |
#       (1)  (2)     (3)  
编辑(添加
修改器的解释)

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


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

这是一个极好的例子。有用的答案和一些解释产生得非常快

回答我自己的问题并不能说明我在做什么。我想感谢撰稿人,给一些可能帮助其他人看这个问题的东西,并解释为什么我选择了一个答案。一个评论似乎不正确,也不够长

下面汇总了每个答案以及我的(谦虚的,并且很高兴被纠正)解释,其中几个包含了回答者的解释。仔细研究答案教会了我很多,并帮助我选择了一个更喜欢的答案。其他人使用非base-R函数,其中一个是创建的函数,它可能很好,但并不容易获得。我喜欢第二个答案,因为它只使用了子功能,但我把月桂花环送给了第五个,因为它优雅地使用了两种技巧,我很高兴学习到这两种技巧。谢谢大家

答案1

gregexpr
使用特殊单词字符
“w+”
,在
“.com”
之前查找任何一个或多个单词,并返回包含长度和使用字节的列表

regmatches
获取找到的
gregexpr
并仅返回已识别的字符串

sub
从每个字符串中删除第一个“.com”[我不确定为什么gsub不起作用,但当您只需要第一个实例时,全局sub可能是一个风险]

ANS 2

内部子模块通过问号特殊字符?处理“http:”和“https:”,这允许“s”是可选的

然后,内部子函数用一个字符类处理一个或多个“/”,该字符类仅包含一个正斜杠,但由
“+”
扩展,即在http中两次://

右侧内部子正则表达式读取的下一部分包括任意数量的字符,这些字符是可选的,
“[.]?

接下来,将“com”之前的句点放在括号中,而不是转义它

然后是“com”,后跟正斜杠[我不确定我是否理解该部分]

“\\1”仅保留子函数提取内容的第一部分

所有上述操作都返回以下内容:

[1] "grand.test"      "example"         "big.time.sample"
最左边的子函数获取内部子函数的结果,并删除括号内句点前面带有“*”的所有字符

答案3

首先,
strsplit
使用垂直管道(生成列表)以正斜杠或句点分隔每个字符串

[[1]]
[1] "http:" ""      "grand" "test"  "com"  

[[2]]
[1] "https:"  ""        "example" "com"    

[[3]]
[1] "http:"  ""       ""       "big"    "time"   "sample" "com"
接下来,一个匿名函数使用
tail
函数查找每个字符串中的最后两个元素,并选择第一个元素,从而整齐地删除每个“.com”

用sapply函数包装这两个步骤将匿名函数的操作矢量化为所有三个字符串

ANS 4

basename
函数返回

[1] "grand.test.com"       "example.com"          ".big.time.sample.com"
从对
basename()
的帮助中,我们了解到“basename将删除最后一个路径分隔符(如果有)之前的所有路径”,这将整齐地删除http://和https://元素

然后,
word()
函数使用负数运算符(start=-2)从末尾提取第二个“word”,前提是se
sub(".com", "", regmatches(urls, gregexpr("(\\w+).com", urls)))
sub('.*[.]','', sub('https?:[/]+[.]?(.*)[.]com[/]','\\1',urls))
[1] "grand.test"      "example"         "big.time.sample"
sapply(strsplit(urls, "/|\\."), function(x) tail(x,2)[1])
[[1]]
[1] "http:" ""      "grand" "test"  "com"  

[[2]]
[1] "https:"  ""        "example" "com"    

[[3]]
[1] "http:"  ""       ""       "big"    "time"   "sample" "com"
library(stringr)
word(basename(urls), start = -2, sep = "\\.")
[1] "grand.test.com"       "example.com"          ".big.time.sample.com"
pat = "(.*?)(\\w+)(\\.com.*)"
gsub(pat, "\\2", urls)
pat = "(.*?)(\\w+)(\\.com.*)"
#        ^    ^       ^
#        |    |       |
#       (1)  (2)     (3)  
regcapturedmatches(urls, regexpr("([^.\\/]+)\\.com", urls, perl=T))