R regex找到最后出现的分隔符

时间:2014-10-09 23:38:46

标签: 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(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"

任何有关此类内容的建议:

    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

编辑: 另一种尝试:

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

4 个答案:

答案 0 :(得分:13)

以下是一些方法。第一个似乎特别直接,第二个特别短。

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)strapplyc 以下是使用特别简短的gsubfn软件包的替代方案。这将返回一个字符矩阵。 strappylyc将匹配返回到括号中模式的各个部分。第一组parantheses匹配@之前的所有内容,第二组括号匹配@之后的所有内容,最后一组括号匹配最后一个点之后的所有内容。

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"

2a)read.pattern read.pattern也可以在gsubfn包中使用(2)中定义的相同pat来完成:

library(gsubfn)
pat <- "(.*)@(.*[.](.*))"
read.pattern(text = strings1, pat, as.is = TRUE)

提供类似于(1)的data.frame,但列名称为V1V2V3

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

 ss <- function(x, pat) do.call(rbind, strsplit(x, pat))
 cbind( ss(strings1, "@"), ss(strings1, ".*[.]")[, -1] )

给出与(2)相同的答案。

4)strsplit / sub 这是(1)和(3)的混合:

cbind(do.call(rbind, strsplit(strings1, "@")), sub(".*[.]", "", strings1))

给出与(2)相同的答案。

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

do.call(rbind, strsplit(sub("(.*[.](.*))", "\\1@\\2", strings1), "@"))

给出与(2)相同的答案。

更新添加了其他解决方案。

答案 1 :(得分:9)

read.table + file_ext方法(不是正则表达式,但非常简单):

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"

答案 2 :(得分:0)

所以这是一个否定的预测regex,应该会给你该行的最后一个.word

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

答案 3 :(得分:0)

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

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