R における正規表現

R の正規表現とそれを用いる関数に付いて解説(ほとんどオンラインヘルプそのもの)します。これらは、オブジェクトの検索や文字列処理、等に使われます。


R における正規表現

R の幾つかの関数はいわゆる正規表現(GNU grep に準ずる)を受け付ける。 例えば、grep,regexp,sub, gsub,strsplit。他にも関数 apropos, browseEnv, help.search, list.files, ls はオブジェクト・ファイル名等に関し正規表現を許す。

詳細

「正規表現 (regular expression)」は文字列のある集合を表すパターンである。 R では三種類の正規表現を使える。

  • grep(extended = TRUE) で使われる「拡張正規表現」
  • grep(extended = FALSE) で使われる「基本正規表現」
  • grep(perl = TRUE) で使われる「パール風正規表現」

関数 apropos, browseEnv, help.search, list.files, ls, strsplit は 拡張正規表現を用いる。strsplit は 'extended = FALSE' オプションで 基本正規表現を用いる。

以下で説明されるパターンは 'cat' で表示される仕方で記述される。 R の文字列をキーボードから入力するには、バックスラッシュ文字 \ を二重化 \\ する必要があることを注意しよう。

拡張正規表現 (既定動作)

POSIX 1003.2 標準に基づく GNU 移植を用いる。既定オプション extended = TRUE の際用いられる正規表現。

  • 正規表現は算術表現と同様、小さな部分表現を結合して得られる
    • 基本的構成要素は単一の文字にマッチする正規表現である 全てのアルファベット文字と数値は、それ自身にマッチする正規表現である
    • メタ文字 特殊な意味を持つメタ文字はその前に バックスラッシュ記号をおくことで表現される。メタ文字は . \ | ( ) [ { ^ $ * + ? である
    • 文字クラス [] ではさまれ 文字のリストは その中のいずれの文字ともマッチする もし最初の文字がカレット^ ならば そのリスト中に無い任意文字列とマッチする。 最初と最後の文字をハイフンで結ぶと文字の範囲を指定する(文字範囲は現在有効ロケールに依存する)。
例
[0123456789] は任意の単一の数値とマッチ
[^abc] は文字 'a', 'b', 'c' 以外の全ての文字とマッチ
  • 幾つかの名前付き文字クラスが予め定義されている(ロケール依存)。これらは実際は [ [:alnum:] ] のように、さらに鈎括弧に入れて使う。
  • [:alnum:] アルファベットと数値、[:alpha:] + [:digit:]
  • [:alpha:] 大小文字アルファベット、 [:lower:] + [:upper:]
  • [:lower:] 小文字アルファベ
  • [:digit:] 数値
  • [:blank:] 空白文字、スペースとタブ
  • [:cntrl:] 制御文字(000-037, 177('DEL')
  • [:graph:] グラフィカル文字 ([:alnum:] と [:punct:])|
  • [:print:] 印字可能な文字、[:alnum:] + [:punct:] + space
  • [:punct:] パンクチュエーション文字 ! " # $ % & ' ( ) * + , - . /
  • [:space:] 空白文字、タブ、改行、水平タブ、給紙、キャリッジリターン、空白
  • [:xdigit:] 16進数 0 1 2 3 4 5 6 7 8 9 A B C D E F a b c d e f
  • 注意
    • :alnum:?[0-9A-Za-z] を意味するが後者はロケールと文字コーディングに依存
    • ほとんどのメタ文字は鍵括弧リスト内では本来の意味を失う
    • ] を鍵括弧リストに入れる際は必ず最初におく
    • ^ を鍵括弧リストに入れる際は最初以外の任意位置におく
    • \ および上の二つの文字だけが鈎括弧リスト内で本来の意味を保つ
    • ピリオッド . は任意の単一文字にマッチする
    • 記号 \w:alnum:? と同義だが、アンダースコアともマッチ
    • \W\w の否定(つまり英数字以外)
    • ^先頭にある空文字列 にマッチ。 つまり、それ以降の表現が文字列の先頭にあることを指示する。
    • $末尾にある空文字列 にマッチ。 つまり、その直前の表現が文字列の末尾にあることを指示する。
    • \<単語の先頭にある空文字列 にマッチ。^ と同じ(?)
    • \>単語の末尾にある空文字列 にマッチ。$ と同じ(?)
    • \b単語の境界にある空文字列 にマッチ
    • \B単語の境界にない空文字列 にマッチ
  • 繰返し指示 (正規表現の後に置き、その繰返しを表現する)
  • ? 直前の項目はオプションであり、零回もしくは一回繰り返す
  • * 直前の項目を零回もしくは一回以上繰り返す
  • + 直前の項目を一回以上繰り返す
  • '{n}' 直前の項目をちょうど n 回繰り返す
  • '{n,}' 直前の項目を n 回以上繰り返す
  • '{n,m}' 直前の項目を n 回以上、最大 m 回繰り返す
  • 注意
    • 繰返しはマッチング可能な最大回数行なわれる
    • 二つの表現は連結することができ、結果は各表現にマッチする文字列を連結した文字列にマッチする
    • 二つの表現を | で並べると、各表現の一方にマッチする正規表現になる。鈎括弧リスト中では | は本来の文字とされる
      例:abba|cde は abba か cde にマッチ
    • 繰返し指示は連結指示に優先し、連結指示は選択指示に優先するので、必要に応じ丸括弧で表現を囲む必要がある
      例:(abba|cde)* と abba|cde* はことなる意味を持つ
    • \N (N は単一の数字) はそれまでにマッチした N 番目の丸括弧で囲まれた正規サブ表現にマッチする。

基本正規表現

オプション extended = FALSE が使われた時の正規表現を説明する。
基本正規表現ではメタ文字 ? + { | ( ) はその特別な意味を失う。代わりにバックスラッシュ付きの \? \+ \{ \| \( \) を使う。従ってメタ文字は . \ [ ^ $ * になる。

Perl 式正規表現

オプション perl = TRUE は Perl 5 互換の正規表現を用いる。 詳細は Perl 文献を参照。

正規表現が使える関数 grep, regexpr, sub, gsub

用法

  • 文字列ベクトル x 中から正規表現 pattern にマッチするものを選び出す。
    • grep(pattern, x, ignore.case = FALSE, extended = TRUE, perl = FALSE, value = FALSE, fixed = FALSE)
    • regexpr(pattern, text, extended = TRUE, perl = FALSE, fixed = FALSE)
  • sub と gsub は文字列ベクトル x 中から正規表現 pattern にマッチするものを選び出し、対応する replacement 中の文字列と置き換える。
    • sub(pattern, replacement, x, ignore.case = FALSE, extended = TRUE, perl = FALSE)
    • gsub(pattern, replacement, x, ignore.case = FALSE, extended = TRUE, perl = FALSE)

引数

  • pattern 与えられた文字列ベクトルとマッチングされる、正規表現を表す一つの文字列 (fixed = TRUE なら文字列)
  • x, text マッチングの対象である文字列ベクトル
  • ignore.case もし FALSE ならマッチングは大文字・小文字を区別する。もし TRUE なら区別されない
  • extended もし TRUE なら拡張正規表現(既定)が用いられる。もしFALSE なら基本正規表現が用いられる
  • perl 論理値。もし可能ならパール互換の正規表現をもちいるか? 拡張正規表現に優先する
  • value もし FALSE なら grep で決定されるマッチングの(整数値の)ベクトル添字が返される。もし TRUE ならマッチングした要素自身が返される。
  • fixed 論理値。もし TRUE なら patternそのもの, as isとしてマッチングされる。他のすべての引数に優先する
  • replacement subgsub でマッチしたものが置き換えられる文字列

詳細

  • 二つの *sub 関数は、sub が最初に見つかった pattern だけを置き換えるのに対して、gsub は見つかったすべてを置き換える点だけが異なる
  • regexpr では patternNA だとエラーになるが、それ以外では NA が許されそれ自身にマッチする。
  • 正規表現は extended 引数の値に応じて、拡張・基本とも POSIX 1003.2 の仕様に従う。もし perl = TRUE ならば PCRE に従う(正確なパターンのセットは使用中のシステムにインストールされている PCRE のバージョンに依存するかも知れない)

返り値

  • grep に対してパターンにマッチした x の成分の 添字 を返す。もし valueTRUE ならマッチした要素が返される。
  • subgsub に対しては元の文字列ベクトルと同じ長さの文字列
  • regexpr に対しては text と同じ長さの整数値ベクトルで、最初のマッチングが見つかった位置を返す。もし一つも見つからなければ -1 が返される。マッチしたテキストの長さを与える属性 match.length を持つ(もしマッチングがなければ値は -1)

その他の関連関数

agrep 近似的なマッチング

tolower, toupper, casefold,

chartr 文字列の変換

charmatch, pmatch, match

apropos は regexpr を用いており、良い例を提供する

ls, objects はオブジェクトの検索に対し、正規表現を受け付ける

glob2rx は Unix の ls 命令におけるようなファイル名のワイルドカード指定を R 風の正規表現に変換する。オプション無しでは先頭を表す^, 末尾を表す $ が付く。

 例 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..$"

幾つかの例

例1 オブジェクトの検索 grep()

> 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

例2 ファイル検索 list.files()

正規表現によるファイル名のリストアップと、その内容を読み込んだデータファイルをリストへ一括格納。名前が "data1.txt", "data12.txt" 等のファイルすべてが対象となる。

tab <- lapply(list.files(pattern="^data[[:digit:]]{1,}.txt"), read.table)
# 各データフレームは tab[[1]],tab[[2]]... で得られる

例3 テキストの置き換え sub, gsub

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

例4

> 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/"))

例5 apropos() オブジェクトをキーワードで検索する

> 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

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Google
WWW を検索 OKADAJP.ORG を検索
Last-modified: 2015-03-01 (日) 01:15:59 (761d)