2010-12-09 49 views
1

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

# 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最接近 - 我会尽力为我工作。

+0

嗯,是不是调用一些shell grep更容易?我该怎么做呢? – 2010-12-09 13:12:09

+0

@ ran2:更正了我的名字:-) – 2010-12-09 13:13:57

+0

oups,对不起,先生!我会仔细检查下次你帮我时是否至少写下了你的名字;) – 2010-12-09 13:17:07

回答

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" 

编辑:

正如尼科说,如果你想为完整的正则表达式做到这一点,您需要使用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

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" 
2

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 
3

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

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

回报"fasdjlk465öfsdj123"

如果你想回到比赛中,你需要将test分解为它的组成部分,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" 
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.

2

strapply在gsubfn包可以这样做提取:

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

其基于所述apply范例,其中第一个参数是对象,第二个是该改性剂(余量apply,为strapply正则表达式)和锡尔d参数是应用于匹配的函数。

str_extract_all(obj, re) in stringr package is similar to strapply专门用于c的功能,即它类似于strapply(obj, re, c)

strapply支持R支持的正则表达式集合,也支持tcl正则表达式。

看到gsubfn主页http://gsubfn.googlecode.com