R における正規表現
R の正規表現とそれを用いる関数に付いて解説(ほとんどオンラインヘルプそのもの)します。これらは、オブジェクトの検索や文字列処理、等に使われます。
R の幾つかの関数はいわゆる正規表現(GNU grep に準ずる)を受け付ける。 例えば、grep,regexp,sub, gsub,strsplit。他にも関数 apropos, browseEnv, help.search, list.files, ls はオブジェクト・ファイル名等に関し正規表現を許す。
「正規表現 (regular expression)」は文字列のある集合を表すパターンである。 R では三種類の正規表現を使える。
関数 apropos, browseEnv, help.search, list.files, ls, strsplit は 拡張正規表現を用いる。strsplit は 'extended = FALSE' オプションで 基本正規表現を用いる。
以下で説明されるパターンは 'cat' で表示される仕方で記述される。 R の文字列をキーボードから入力するには、バックスラッシュ文字 \ を二重化 \\ する必要があることを注意しよう。
POSIX 1003.2 標準に基づく GNU 移植を用いる。既定オプション extended = TRUE の際用いられる正規表現。
例 [0123456789] は任意の単一の数値とマッチ [^abc] は文字 'a', 'b', 'c' 以外の全ての文字とマッチ
例:abba|cde は abba か cde にマッチ
例:(abba|cde)* と abba|cde* はことなる意味を持つ
オプション extended = FALSE が使われた時の正規表現を説明する。
基本正規表現ではメタ文字 ? + { | ( ) はその特別な意味を失う。代わりにバックスラッシュ付きの \? \+ \{ \| \( \) を使う。従ってメタ文字は
. \ [ ^ $ * になる。
オプション perl = TRUE は Perl 5 互換の正規表現を用いる。 詳細は Perl 文献を参照。
例 glob2rx("abc.*") -> "^abc\\."
glob2rx("a?b.*") -> "^a.b\\."
glob2rx("a?b.*", trim.tail=FALSE) -> "^a.b\\..*$"
glob2rx("*.doc") -> "^.*\\.doc$"
glob2rx("*.doc", trim.head=TRUE) -> "\\.doc$"
glob2rx("*.t*") -> "^.*\\.t"
glob2rx("*.t??") -> "^.*\\.t..$"
> z <- ls() # 現在のオブジェクトリスト(文字列ベクトル)
> zz <- grep("ab", z); z[zz] # ab を名前の一部に含むオブジェクト
[1] "ab" "abab" "abcdab" "abdce" "cdabcd" "cdcdab"
> zz <- grep("ab|cd", z); z[zz] # ab か cd を名前の一部に含むオブジェクト
[1] "ab" "abab" "abcdab" "abdce" "cd" "cdabcd" "cdcd" "cdcdab"
> zz <- grep("\\<ab", z); z[zz] # ab を名前の先頭に含むオブジェクト
[1] "ab" "abab" "abcdab" "abdce"
> zz <- grep("cd\\>", z); z[zz] # cd を名前の最後に含むオブジェクト
[1] "cd" "cdabcd" "cdcd"
> zz <- grep("(ab){2}", z); z[zz] # abab を名前の一部に含むオブジェクト
[1] "abab"
> letters[grep("[a-z]", letters)]
[1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s"
[20] "t" "u" "v" "w" "x" "y" "z"
> txt <- c("arm","foot","lefroo", "bafoobar")
> if(any(i <- grep("foo",txt))) cat("'foo' appears at least once in\n\t",txt,"\n")
'foo' appears at least once in
arm foot lefroo bafoobar
> txt[i]
[1] "foot" "bafoobar"
> i
[1] 2 4
正規表現によるファイル名のリストアップと、その内容を読み込んだデータファイルをリストへ一括格納。名前が "data1.txt", "data12.txt" 等のファイルすべてが対象となる。
tab <- lapply(list.files(pattern="^data[[:digit:]]{1,}.txt"), read.table)
# 各データフレームは tab[[1]],tab[[2]]... で得られる
# a もしくは b を二重化する。
# \1 はマッチングされたパターン [ab] (a もしくは b) を表す
# \1 は実際は \\1 とする必要があることを注意
> gsub("([ab])", "\\1\\1", "abc and ABC")
[1] "aabbc aand ABC"
# sub は最初のマッチングだけを置き換える
> sub("([ab])", "\\1\\1", "abc and ABC")
[1] "aabc and ABC"
> txt <- c("The", "licenses", "for", "most", "software", "are",
"designed", "to", "take", "away", "your", "freedom",
"to", "share", "and", "change", "it.",
"", "By", "contrast,", "the", "GNU", "General", "Public", "License",
"is", "intended", "to", "guarantee", "your", "freedom", "to",
"share", "and", "change", "free", "software", "--")
> (i <- grep("[gu]", txt))
[1] 7 11 16 24 29 30 35
> (i <- grep("[gu]", txt, value=TRUE)) # g か u を含む文字列(添字ではなくそ文字列そのもの)
[1] "designed" "your" "change" "Public" "guarantee" "your"
[7] "change"
# 大文字の G を含む文字列
> txt[gsub("g","#", txt) != gsub("g","#", txt, ignore.case = TRUE)]
[1] "GNU" "General"
# 返り値 -1 はマッチしなかったことを示す
# 値 4 は該当文字列の第4文字目以降にマッチしたことを示す
# 属性 ”match.length" の値 2 は二文字分マッチしたという意味
> regexpr("en", txt)
[1] -1 4 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 -1 4
[26] -1 4 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
attr(,"match.length")
[1] -1 2 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 -1 2
[26] -1 2 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
> str = 'Now is the time ' # 末尾に複数の空白を含む文字列
> sub(' +$', '', str) # 末尾の空白をあるだけ取り除く
[1] "Now is the time"
> sub('[[:space:]]+$', '', str) # 同じことを POSIX-style で実行
[1] "Now is the time"
> ls(pat="0$") # 末尾が 0 で終るオブジェクトのリスト [1] "F10" "fitlm0" "sfun0" "x0" "y0" > ls(pat="[0-9]$") # 末尾が数字で終るオブジェクトのリスト [1] "DNase1" "F10" "Fn12" "cloud1" "cloud2" > rm(list=ls(pat="[0-9]$")) # 末尾が数字で終るオブジェクトを消去 > ls(pat="[0-9]$") # もう無い character(0)
# ディレクトリ "c:/data/" (MS Windows の場合)にあるファイルの拡張子を除いた名前を得る(リスト形式で)
# 最初のブロック ([^.]+) はファイル名先頭 ^ にある任意の一文字 . の任意繰返し + を意味する
# 次のブロック (\\..+) はドット文字 \\. の次に任意一文字 . とその任意繰返し + を意味する
# 丸括弧で囲みブロック化することにより、\\1 で最初のブロックでマッチした文字列を表現できる
# つまり、\\1 でファイル名のドット文字より前の部分全部を意味する
filename <- sub("([^.]+)(\\..+)", "\\1", dir("c:/data/"))
> apropos("lm") # "lm" を名前に含むオブジェクト、apropos(lm) でも良い
[1] ".__C__anova.glm" ".__C__anova.glm.null" ".__C__glm"
[4] ".__C__glm.null" ".__C__lm" ".__C__mlm"
[7] "KalmanForecast" "KalmanLike" "KalmanRun"
[10] "KalmanSmooth" "add1.glm" "add1.lm"
[13] "add1.mlm" "alias.lm" "anova.glm"
以下略
aprops> apropos("\\[") # [ で始まる関数オブジェクト
[1] "[" "[.AsIs" "[.POSIXct" "[.POSIXlt"
[5] "[.data.frame" "[.difftime" "[.factor" "[.formula"
[9] "[.getAnywhere" "[.noquote" "[.terms" "[.ts"
[13] "[<-" "[<-.POSIXct" "[<-.POSIXlt" "[<-.data.frame"
[17] "[<-.factor" "[[" "[[.POSIXct" "[[.data.frame"
[21] "[[<-" "[[<-.data.frame"
> length(apropos(".")) # すべてのオブジェクトの数
[1] 2104
> apropos("^pr") # pr で始まるオブジェクト
[1] "promptClass" "promptMethods" "prototype"
[4] "prop.test" "prop.trend.test" "prcomp"
[7] "princomp" "promax" "profiler"
以下略
> apropos("^.$") # 一文字の名前のオブジェクト
[1] "x" "!" "$" "&" "(" "*" "+" "-" "/" ":" "<" "=" ">" "?" "@" "C" "D" "F" "I"
[20] "T" "[" "^" "c" "q" "t" "{" "|" "~"
> apropos("^..?$") # 高々二文字のオブジェクト
[1] "x" "as" "el" "is" "ar" "!" "!=" "$" "%%" "&" "&&" "(" "*" "+" "-"
[16] ".C" "/" ":" "::" "<" "<-" "<=" "=" "==" ">" ">=" "?" "@" "C" "D"
[31] "F" "I" "Im" "Re" "T" "[" "[[" "^" "by" "c" "cm" "de" "df" "dt" "gc"
[46] "gl" "if" "lm" "ls" "pf" "pi" "pt" "q" "qf" "qr" "qt" "rf" "rm" "rt" "sd"
[61] "t" "ts" "vi" "{" "|" "||" "~"
> apropos("^.{2,4}$") # 2-4文字のオブジェクト
[1] "@<-" "Math" "Ops" "as" "as<-" "el" "el<-" "is" "new" "show"
[11] "slot" "dist" "ppr" "nls" "acf" "ar" "ccf" "lag" "pacf" "stl"
[21] "!=" "$<-" "%%" "%*%" "%/%" "%in%" "%o%" "%x%" "&&" ".C"
[31] "::" ":::" "<-" "<<-" "<=" "==" ">=" "AIC" "Arg" "Conj"
以下略
> length(apropos("^.{8,}$")) # 8文字以上の名前のオブジェクトの総数
[1] 1378