一所懸命に手抜きする

監査の仕事をしています。ITを利用し、良い意味で「手抜き」することは効率化と精度アップに役立つと思うんです。部下への引き継ぎのためにまずは諸々頭から引っ張り出そうとブログを始めました。

[ Main ]  [ 別館 ]
当ブログで取り上げられている事案やデータベース、人物等はすべてフィクションです。

パターンにマッチした部分文字列を返すR標準関数 regmatches()

Rは標準では一致する文字列を一発で抽出できないらしい

 正規表現と言えば grep を思い浮かべるのですが、次の例では、検索パターンに一致する要素番号か、一致する要素そのものを戻り値としています。

grep("太.*?郎",c("山田太郎","鈴木太一郎"))
[1] 1 2
grep("太.*?郎",c("山田太郎","鈴木太一郎"),value=TRUE)
[1] "山田太郎"   "鈴木太一郎"

 上の例では検索パターンに一致した部分文字列「太郎」「太一郎」だけを抽出することはできません。
 stringr というライブラリがあり、文字列を処理する関数が多数用意されています。そこには検索パターンに一致した部分文字列を返す str_extract() や str_match() という関数が用意されています。
 標準では対処できないのでしょうか。

R標準でもあわせ技で部分文字列を抽出できる

検索パターンに一致する部分の開始位置と長さを得る

① regexpr()
 検索パターンに一致する部分の開始位置と長さ等を返す regexpr() を使ってみます。
oSql<-"select b1,b2 from LibA.x where a=( select x1 from LibB.y where v1=2)"
(match<-regexpr("select.?from",oSql))
[1] 1
attr(,"match.length")
[1] 17
attr(,"useBytes")
[1] TRUE
 戻り値として一致した文字列の開始位置等が得られます。  しかし、select b1…の開始位置1はマッチしていますが、select x1の36はマッチしていません。regexprは最初にマッチしたものだけを返します。
注意
match[2]
[1] NA
attr(match,"match.length")
[1] 17
regexpr("select.?from","update tab1 set x where y=12")
[1] -1
attr(,"match.length")
[1] -1
attr(,"useBytes")
[1] TRUE

 一致した文字列の長さなどは一見[2]に格納されるようにも見えますが、そうではないため上の例ではNAとなっています。
 attr(,"match.length")とあるように、要素の属性(attributes)として格納されます。そのため必要ならattr()などで呼び出すことになります。
 またマッチしない場合には、開始位置-1、長さ-1となります。
 ここまでわかれば
 substr(oSql,match,attr(match,"match.length"))
[1] "select b1,b2 from"
 のように抜き出すこともできます。
② gregexpr()
 regexpr が複数マッチに対応していなかったのに対して、gregexpr は複数マッチに対応しています。
(match <- gregexpr("select.*?from",oSql))
[[1]]
[1]  1 36
attr(,"match.length")
[1] 17 14
attr(,"useBytes")
[1] TRUE
 この例では、最初にマッチしたのは開始位置1,長さ17、二つ目にマッチしたのは36文字目から14文字ということになります。

マッチ部分の開始位置・長さ等から文字列を抽出する regmatches()

 regmatches()はgregexpr()やregexpr()で渡される(複数の)抽出開始位置/長さ情報から文字列を抽出します。
 match <- gregexpr("select.*?from",oSql)
(coreSqlText<-regmatches(oSql, match)[[1]])
[1] "select b1,b2 from" "select x1 from"  

広告を非表示にする