R regex查找最后一次出现的分隔符

R regex查找最后一次出现的分隔符,regex,r,string,Regex,R,String,我正在尝试获取电子邮件地址(即.net、.com、.edu等)的结尾,但是@后面的部分可以有多个句点 library(stringi) strings1 <- c( 'test@aol.com', 'test@hotmail.com', 'test@xyz.rr.edu', 'test@abc.xx.zz.net' ) list1 <- stri_split_fixed(strings1, "@", 2) df1 <- data.frame(

我正在尝试获取电子邮件地址(即.net、.com、.edu等)的结尾,但是@后面的部分可以有多个句点

library(stringi)

strings1 <- c(
    'test@aol.com',
    'test@hotmail.com',
    'test@xyz.rr.edu',
    'test@abc.xx.zz.net'
)

list1 <- stri_split_fixed(strings1, "@", 2)
df1 <- data.frame(do.call(rbind,list1))

    > list2 <- stri_split_fixed(df1$X2, '.(?!.*.)', 2);list2
[[1]]
[1] "aol.com"

[[2]]
[1] "hotmail.com"

[[3]]
[1] "xyz.rr.edu"

[[4]]
[1] "abc.xx.zz.net"
编辑: 另一次尝试:

> list2 <- stri_split_fixed(df1$X2, '\.(?!.*\.)\w+', 2);list2
Error: '\.' is an unrecognized escape in character string starting "'\."

以下是一些方法。第一个看起来特别笔直,第二个看起来特别短

1)sub可通过在R中应用
sub
生成每列:

data.frame(X1 = sub("@.*", "", strings1), 
           X2 = sub(".*@", "", strings1), 
           X3 = sub(".*[.]", "", strings1), 
           stringsAsFactors = FALSE)
给予:

    X1            X2  X3
1 test       aol.com com
2 test   hotmail.com com
3 test    xyz.rr.edu edu
4 test abc.xx.zz.net net
2)STRAPLYC这里有一个使用特别短的gsubfn包的替代方案。这将返回一个字符矩阵<代码>Strapylyc返回与括号中模式部分的匹配项。第一组括号匹配@之前的所有内容,第二组括号匹配@之后的所有内容,最后一组括号匹配最后一个点之后的所有内容

library(gsubfn)
pat <- "(.*)@(.*[.](.*))"
t(strapplyc(strings1, pat, simplify = TRUE))

     [,1]   [,2]            [,3] 
[1,] "test" "aol.com"       "com"
[2,] "test" "hotmail.com"   "com"
[3,] "test" "xyz.rr.edu"    "edu"
[4,] "test" "abc.xx.zz.net" "net"
提供类似于(1)的data.frame,但列名为
V1
V2
V3

3)strsplit重叠提取使得使用
strsplit
很困难,但我们可以使用
strsplit
的两个应用程序。第一个
strsplit
在@处拆分,第二个使用直到最后一个点的所有内容进行拆分。最后一个
strsplit
总是生成一个空字符串作为第一个拆分字符串,我们使用
[,-1]
删除它。这给出了一个字符矩阵:

 ss <- function(x, pat) do.call(rbind, strsplit(x, pat))
 cbind( ss(strings1, "@"), ss(strings1, ".*[.]")[, -1] )
给出与(2)相同的答案

4a)这是另一种使用
strsplit
sub
的方法。在这里,我们附加一个@,后跟TLD,然后在@上拆分

do.call(rbind, strsplit(sub("(.*[.](.*))", "\\1@\\2", strings1), "@"))
给出与(2)相同的答案


更新添加了额外的解决方案。

因此,这是一个否定的前瞻
regex
,应该为您提供该行的最后一个
.word

\.(?!.*\.)\w+       

一种
read.table
+
file\u ext
方法(不是正则表达式,但相当简单):


使用基本正则表达式的解决方案,假设df1$X2是字符向量:

df1 <- cbind(df1, X3 = regmatches(df1$X2, regexpr('\\.[A-Z|a-z]*$', df1$X2)))
df1$X3 <- gsub("\\.", "", df1$X3)

df1您想要的结果与您的
strings1
vector@RichardScriven:您说得对,很好,谢谢。使用
stringi
您还可以执行
data.frame(stri_-match(strings1,regex=“(.*)@(.[.](.])”)[,-1])
,从其中一个回答中借用regex,第一个子项替换@以及其后的所有内容(.*)不带任何内容“”,第二个将不带任何内容的所有内容(.*)替换为@,第三个将不带任何内容的所有内容(.*)替换为不带任何内容的点([.])
stringsasfaaactors=FALSE
是可选的,可确保结果存储为字符而不是因子。语法不正确并不意味着正则表达式不正确。你自己试试吧,太好了。简短、有效、简洁。R基本包中有许多隐藏的宝石,如
utils
tools
file_ext
基本上只是一个
regexpr
包装器,但它很整洁,已经为您整理好了。
do.call(rbind, strsplit(sub("(.*[.](.*))", "\\1@\\2", strings1), "@"))
\.(?!.*\.)\w+       
dat <- read.table(text=strings1, sep="@")
dat$V3 <- tools::file_ext(strings1)
dat

##     V1            V2  V3
## 1 test       aol.com com
## 2 test   hotmail.com com
## 3 test    xyz.rr.edu edu
## 4 test abc.xx.zz.net net
do.call(rbind, strsplit(strings1, "@|\\.(?=[^\\.]+$)", perl=TRUE))

##     [,1]   [,2]        [,3] 
## [1,] "test" "aol"       "com"
## [2,] "test" "hotmail"   "com"
## [3,] "test" "xyz.rr"    "edu"
## [4,] "test" "abc.xx.zz" "net"
df1 <- cbind(df1, X3 = regmatches(df1$X2, regexpr('\\.[A-Z|a-z]*$', df1$X2)))
df1$X3 <- gsub("\\.", "", df1$X3)