簡體   English   中英

如何在 R 中使用帶有參數的 grep?

[英]How can I use grep with parameters in R?

顯然我不明白 grep 在 R 中的工作方式。如果我在我的 OS X 終端上使用 grep,我可以使用參數 -o 這使得 grep 只返回匹配的部分。 在 R 中,我找不到如何做相應的事情。 閱讀手冊我認為 values 是正確的方法,因為它返回字符而不是索引,但仍然返回整個字符串,所以更好。

# 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 最接近——我會盡力讓它對我有用。

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"

編輯2:

對於向量,使用函數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

那是因為 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" 

所有這些與字符串一起跳舞的問題都是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 中只執行一步。

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

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

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

返回"fasdjlk465öfsdj123"

如果要返回匹配項,則需要將test分解為它的組成部分,對這些部分進行grep ,然后使用從grep返回的內容到 index 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"

strapply包中的 stripply 可以做這樣的提取:

> 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)在stringr包類似於strapply專門在使用c為函數,即,其將類似於strapply(obj, re, c)

strapply支持 R 支持的正則表達式集,也支持 tcl 正則表達式。

請參閱http://gsubfn.googlecode.com 上的 gsubfn 主頁

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM