grepとユカイな仲間たち

by
カテゴリ:
タグ:

?grepすると色んな関数が並んでるけど、違いをよくわかってなかったので、改めて試す。

実験

fruits <- c("apple", "banana", "prune")

grep関数はマッチした要素のインデックスを返す。

grep("p", fruits)
#> [1] 1 3

grepl関数はマッチしたか否かの真偽値を返す。

grepl("p", fruits)
#> [1]  TRUE FALSE  TRUE

regexpr関数は最初にマッチした箇所が何文字目で、何文字から成るか返す。

regexpr("p", fruits)
#> [1]  2 -1  1
#> attr(,"match.length")
#> [1]  1 -1  1
#> attr(,"index.type")
#> [1] "chars"
#> attr(,"useBytes")
#> [1] TRUE
regexpr("p+", fruits)
#> [1]  2 -1  1
#> attr(,"match.length")
#> [1]  2 -1  1
#> attr(,"index.type")
#> [1] "chars"
#> attr(,"useBytes")
#> [1] TRUE
regexpr("[ap]+", fruits)
#> [1] 1 2 1
#> attr(,"match.length")
#> [1] 3 1 1
#> attr(,"index.type")
#> [1] "chars"
#> attr(,"useBytes")
#> [1] TRUE

gregexpr関数はregexpr関数の複数マッチ版。

gregexpr("[ap]+", fruits)
#> [[1]]
#> [1] 1
#> attr(,"match.length")
#> [1] 3
#> attr(,"index.type")
#> [1] "chars"
#> attr(,"useBytes")
#> [1] TRUE
#> 
#> [[2]]
#> [1] 2 4 6
#> attr(,"match.length")
#> [1] 1 1 1
#> attr(,"index.type")
#> [1] "chars"
#> attr(,"useBytes")
#> [1] TRUE
#> 
#> [[3]]
#> [1] 1
#> attr(,"match.length")
#> [1] 1
#> attr(,"index.type")
#> [1] "chars"
#> attr(,"useBytes")
#> [1] TRUE

regexec関数はregexpr関数の返り値がリストになったもの

regexec("p", fruits) |> str()
#> List of 3
#>  $ : int 2
#>   ..- attr(*, "match.length")= int 1
#>   ..- attr(*, "index.type")= chr "chars"
#>   ..- attr(*, "useBytes")= logi TRUE
#>  $ : int -1
#>   ..- attr(*, "match.length")= int -1
#>   ..- attr(*, "index.type")= chr "chars"
#>   ..- attr(*, "useBytes")= logi TRUE
#>  $ : int 1
#>   ..- attr(*, "match.length")= int 1
#>   ..- attr(*, "index.type")= chr "chars"
#>   ..- attr(*, "useBytes")= logi TRUE

grepexec関数はgregexpr関数のマッチ開始箇所をmatrixで表現したもの

gregexec("p", fruits) |> str()
#> List of 3
#>  $ : int [1, 1:2] 2 3
#>   ..- attr(*, "match.length")= int [1, 1:2] 1 1
#>   ..- attr(*, "useBytes")= logi TRUE
#>   ..- attr(*, "index.type")= chr "chars"
#>  $ : int -1
#>   ..- attr(*, "match.length")= int -1
#>   ..- attr(*, "index.type")= chr "chars"
#>   ..- attr(*, "useBytes")= logi TRUE
#>  $ : int [1, 1] 1
#>   ..- attr(*, "match.length")= int [1, 1] 1
#>   ..- attr(*, "useBytes")= logi TRUE
#>   ..- attr(*, "index.type")= chr "chars"

使い分け

  • 最初にマッチした箇所の情報が欲しいならregexp
  • マッチした全箇所の情報が欲しいなら、解像度の低い順から
    • grep
    • grepl
    • gregexp
  • regexec/gregexecの方が情報は多いかもしれないが出番は少なそう

ちなみにgreplの方が解像度が高い根拠は返り値をwhich関数に与えるとからgrep関数相当になるから。 grep関数は入力した文字列ベクトルの長さ情報を失うので、返り値だけではgrepl関数の返り値を作れない。

which(grepl("p", fruits))
#> [1] 1 3
grep("p", fruits)
#> [1] 1 3

Enjoy