如何在R中使用带参数的grep?

时间:2010-12-09 11:51:27

标签: regex r grep

显然我没有得到grep在R中工作的方式。如果我在OS X终端上使用grep,我可以使用参数-o,这使得grep只返回匹配的部分。在R中,我找不到如何做相应的事情。阅读手册我认为值是正确的方法,这更好,因为它返回字符而不是索引,但仍返回整个字符串。

# some string  fasdjlk465öfsdj123 
# R
test <-  fasdjlk465öfsdj123 
grep("[0-9]",test,value=TRUE) # returns  "fasdjlk465öfsdj123"

# shell
grep -o '[0-9]' fasdjlk465öfsdj123
# returns 4 6 5 1 2 3

我在R中缺少的参数是什么?

编辑:Joris Meys的建议非常接近我想要做的事情。我得到一个矢量作为readLines的结果。我想检查向量的每个元素是否有数字并返回这些数字。我真的很惊讶没有标准的解决方案。我想过使用一些可以在字符串上运行的regexp函数并像grep -o一样返回匹配,然后在该向量上使用lapply。 grep.custom最接近 - 我会尝试让它为我工作。

6 个答案:

答案 0 :(得分:5)

这是因为R的'grep'适用于向量 - 它将对每个元素进行搜索并返回匹配的元素索引。它说'这个矢量中的哪些元素符合这个模式?'例如,在这里我们制作一个3的向量,然后问'这个向量中哪些元素中有一个数字?'

> test = c("fasdjlk465öfsdj123","nonumbers","123")
> grep("[0-9]",test)
[1] 1 3

元素1和3 - 不是2,只是字符。

你可能想要gsub - 替换任何与数字无关的东西:

> gsub("[^0-9]","",test)
[1] "465123" ""       "123" 

答案 1 :(得分:5)

Spacedman已经说过了。如果你真的想在shell中模拟grep,你必须使用strsplit()处理字符本身:

> chartest <- unlist(strsplit(test,""))
> chartest
 [1] "f" "a" "s" "d" "j" "l" "k" "4" "6" "5" "ö" "f" "s" "d" "j" "1" "2" "3"
> grep("[0-9]",chartest,value=T)
[1] "4" "6" "5" "1" "2" "3"

编辑:

正如Nico所说,如果你想为完整的正则表达式做这件事,你需要使用gregexpr()substr()。我会像这样制作一个自定义函数:

grep.custom <- function(x,pattern){
    strt <- gregexpr(pattern,x)[[1]]
    lngth <- attributes(strt)$match.length
    stp <- strt + lngth - 1
    apply(cbind(strt,stp),1,function(i){substr(x,i[1],i[2])})
}

然后:

> grep.custom(test,"sd")
[1] "sd" "sd"
> grep.custom(test,"[0-9]")
[1] "4" "6" "5" "1" "2" "3"
> grep.custom(test,"[a-z]s[a-z]")
[1] "asd" "fsd"

EDIT2:

对于向量,使用函数Vectorize(),例如:

> X <- c("sq25dfgj","sqd265jfm","qs55d26fjm" )
> v.grep.custom <- Vectorize(grep.custom)
> v.grep.custom(X,"[0-9]+")
$sq25dfgj
[1] "25"

$sqd265jfm
[1] "265"

$qs55d26fjm
[1] "55" "26"

如果你想从shell调用grep,请参阅?system

答案 2 :(得分:4)

所有这些都是用字符串跳舞是stringr包旨在解决的问题。

library(stringr)
str_extract_all('fasdjlk465fsdj123', '[0-9]')

[[1]]
[1] "4" "6" "5" "1" "2" "3"

# It is vectorized too
str_extract_all(rep('fasdjlk465fsdj123',3), '[0-9]')

[[1]]
[1] "4" "6" "5" "1" "2" "3"

[[2]]
[1] "4" "6" "5" "1" "2" "3"

[[3]]
[1] "4" "6" "5" "1" "2" "3"

stringr背后的动机是在两个原则下统一R中的字符串操作:

  • 为函数(str_do_something)使用合理且一致的命名方案。

  • 使其成为所有在其他编程语言中迈出一步的字符串操作,而在R中只有50步,在R中只需要一步。

答案 3 :(得分:3)

grep只会告诉您字符串是否匹配。

例如,如果你有:

values <- c("abcde", "12345", "abc123", "123abc")

然后

grep <- ("[0-9]", values)
[1] 2 3 4

这告诉您数组的元素2,3和4与正则表达式匹配。你可以传递value=TRUE来返回字符串而不是索引。

如果您想查看匹配发生的位置,可以使用regexpr代替

> regexpr("[0-9]", values)
[1] -1  1  4  1
attr(,"match.length")
[1] -1  1  1  1

告诉你第一场比赛的发生地点。

更好的是,您可以使用gregexpr进行多次匹配

> gregexpr("[0-9]", values)
[[1]]
[1] -1
attr(,"match.length")
[1] -1

[[2]]
[1] 1 2 3 4 5
attr(,"match.length")
[1] 1 1 1 1 1

[[3]]
[1] 4 5 6
attr(,"match.length")
[1] 1 1 1

[[4]]
[1] 1 2 3
attr(,"match.length")
[1] 1 1 1

答案 4 :(得分:3)

不知道你在哪里得到的印象

> test <- "fasdjlk465öfsdj123"
> grep("[0-9]",test)
[1] 1

返回"fasdjlk465öfsdj123"

如果要返回匹配项,则需要将test分解为其中的组件部分grep,然后使用从grep返回的内容来索引test }。

> test <- strsplit("fasdjlk465öfsdj123", "")[[1]]
> matched <- grep("[0-9]", test)
> test[matched]
[1] "4" "6" "5" "1" "2" "3"

或者直接返回匹配的字符串,取决于你想要的内容:

> grep("[0-9]", test, value = TRUE)
[1] "4" "6" "5" "1" "2" "3"

答案 5 :(得分:2)

gsubfn包中的

strapply可以进行这样的提取:

> library(gsubfn)
> strapply(c("ab34de123", "55x65"), "\\d+", as.numeric, simplify = TRUE)
     [,1] [,2]
[1,]   34   55
[2,]  123   65

它基于apply范例,其中第一个参数是对象,第二个是修饰符(apply的边距,strapply的正则表达式),第三个参数是适用于比赛的功能。

stringr包中的

str_extract_all(obj, re)类似于strapply专门用于函数的c,即它类似于strapply(obj, re, c)

strapply支持R支持的正则表达式集,并且还支持tcl正则表达式。

请参阅http://gsubfn.googlecode.com

上的gsubfn主页
相关问题