显然我没有得到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最接近 - 我会尝试让它为我工作。
答案 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)
strapply
可以进行这样的提取:
> library(gsubfn)
> strapply(c("ab34de123", "55x65"), "\\d+", as.numeric, simplify = TRUE)
[,1] [,2]
[1,] 34 55
[2,] 123 65
它基于apply
范例,其中第一个参数是对象,第二个是修饰符(apply
的边距,strapply
的正则表达式),第三个参数是适用于比赛的功能。
str_extract_all(obj, re)
类似于strapply
专门用于函数的c
,即它类似于strapply(obj, re, c)
。
strapply
支持R支持的正则表达式集,并且还支持tcl正则表达式。