正規表現
-
- 正規表現とは
- メタ文字
- 正規表現は,あまり分かりやすい記述方法ではありません.できる限り使用は避けた方が良いと思います
- 正規表現とは
- 正規表現( regular expression )とは,文字列の集合を一つの文字列で表現する方法の一つです.例えば,”book”と”cook”という 2 つの文字列を,正規表現を使用して”[bc]ook”という 1 つの文字列で表現できます.なぜなら,[bc] は,正規表現において,「 b か c かどちらか 1 文字」ということを意味しているからです.Java,Perl,PHP などの言語は正規表現を扱うことができるため,パターンマッチを行うプログラムを容易に作成することができます.
- 正規表現では,「複数の文字列を一つの形式で表現する」ために,いくつかの文字に対して特別な意味を与えています.これらの文字を,「メタ文字」と呼んでいます.メタ文字と普通の文字を区別するために,Ruby では以下に示すような規則を設定しています.
- \ を伴わない英数字はメタ文字ではない.
- \ を伴う記号はメタ文字ではない( `\*' は「繰り返し」でなく「アスタリスク」を表す)
- 正規表現も,Ruby ではオブジェクトの一つです( Regexp クラスのインスタンス).正規表現オブジェクトは,どのような文字とマッチするのかを表すパターンを正規表現で定められた規則に沿って記述し,スラッシュで囲んで表します.例えば,先の例の場合は,
- /[bc]ook/
- となります.なお,以下に示す例のように,%r (% 記法)を使用して,スラッシュの代わりに別の記号を使用することも可能です.
- %r{[bc]ook}
- %r![bc]ook!
- 正規表現の最後の / の直後の文字は,正規表現に対するオプションになります.例えば,
- /[bc]ook/i
- では,大文字と小文字を区別しません.オプションには,以下に示すようなものがあります.
- i 正規表現はマッチ時に大文字小文字の区別を行わない
- o 一番最初に正規表現の評価が行われた時に一度だけ式展開を行う
- x 正規表現中の空白(改行も含む)を無視する.また,バックスラッシュでエスケープしない # から改行までをコメントとみなして無視する.
- m 複数行モード.正規表現「 . 」が,改行にもマッチするようになる.
- 正規表現オブジェクトが対象の文字列にマッチしているかどうかを調べるために,=~ 演算子が用意されています.
- 正規表現オブジェクト =~ string # 「string =~ 正規表現オブジェクト」も可
- のように記述し,正規表現オブジェクトが右辺の文字列オブジェクトにマッチした場合には,マッチした位置のインデックスを返します.インデックスは対象の文字列の先頭の文字位置を 0 とし,パターンにマッチした最初の文字の位置です.マッチしなかった場合は nil が返されます.例えば,先の例を irb を使用して実行すると以下に示すような結果が得られます(以下の例においても同様ですが,ここでは,irb によって実行した結果を示します).
- /[bc]ook/ =~ "textbook" # => 4
- /[bc]ook/ =~ "textbooj" # => nil
- 正規表現オブジェクトを作成するには Regexp クラスの new メソッドを使っても可能です.例えば,例に示したオブジェクトと同じオブジェクトを生成するためには,
- str = Regexp.new("[bc]ook")
- のようにして行います.
- メタ文字
- ^ 行頭.文字列の先頭や改行文字の直後の位置. 例: /^/ =~ "book" # => 0
- $ 行末.文字列の末尾や改行文字の直前の位置. 例: /$/ =~ "book" # => 4
- . 改行を除く任意の 1 文字. 例: /..oo./ =~ "testbook" # => 3
- \w 英数字. 例: /\w/ =~ ">!0ab" # => 2
- \W 非英数字. 例: /\W/ =~ ">!0ab" # => 0
- \s 空白文字であり,[ \t\n\r\f] と同じ. 例: /\s/ =~ "ab cd" # => 2
- \S 非空白文字. 例: /\S/ =~ "ab cd" # => 0
- \d 数字. 例: /\d/ =~ "ab12cd" # => 2
- \D 非数字. 例: /\D/ =~ "ab12cd" # => 0
- \A 文字列先頭.^ とは異なり改行の有無には影響しない. 例: /\A/ =~ "abcd" # => 0
- \Z 文字列末尾.文字列が改行で終っていれば,その改行の直前にマッチ. 例: /\Z/ =~ "abcd" # => 4
- \z 文字列末尾.$ や \Z とは異なり改行の有無には影響しない. 例: /\z/ =~ "abcd" # => 4
- [ ] 文字クラス指定.[] 内に列挙したいずれかの 1 文字にマッチする.例えば,/[abc]/ は,"a", "b", "c" いずれか 1 文字にマッチする.
- ASCII コード順で連続する文字列を指定したい場合は.間に `-' を置いて /[a-c]/ のように書くこともできる.また,先頭,末尾にある `-' は,その文字そのものとマッチする.
- /[a-c]/ =~ "e-fabcd" # => 3
- /[-cd]/ =~ "e-fabcd" # => 1
- /[cd-]/ =~ "e-fabcd" # => 1
- 先頭が `^' であれば,その後に指定した文字以外の 1 文字とマッチする.また,先頭以外にある `^' はその文字そのものとマッチする.
- /[^a-c]/ =~ "abcdef" # => 3
- /[ef^c]/ =~ "abcdef" # => 2
- [] 内には,文字列と同じバックスラッシュ記法と,正規表現 \w, \W, \s, \S, \d, \D が使用できる.
- /[xy\d]/ =~ "ab12cdef" # => 2
- \b 文字クラス指定の外では語境界(英数字と非英数字との境界),文字クラス指定内ではバックスペース.
- 例: /\b/ =~ "ab>!cdef" # => 0
- 例: /\b/ =~ ">!cdef" # => 2
- \B 非語境界.
- 例: /\B/ =~ "ab>!cdef" # => 1
- 例: /\B/ =~ ">!cdef" # => 0
- \G 前回マッチした箇所の直後にマッチ.ただし,初回だけは先頭位置にマッチする.組み込み関数 scan や gsub で使用できる.なお,scan は,正規表現に対して繰り返しマッチを行い,マッチした部分文字列の配列を返すメソッドである.
.
- 例: "abcefg hij".scan(/\w\w\w/) # => ["abc", "efg", "hij"]
- "abcefg hij".scan(/\G\w\w\w/) # => ["abc", "efg"]
- ( ) 正規表現のグループ化.括弧の中の正規表現にマッチした文字列は後方参照のために記憶される.
- \1, \2, ... ,\n 後方参照.指定した箇所に,その前にある n 番目の括弧の内容を展開する
- 例: /(ab)cd\1/ =~ "ababcdabef" # => 2
- /abcdab/ =~ "ababcdabef" と同じ
- 例: /ab(cd)\1/ =~ "ababcdcdabef" # => 2
- /abcdcd/ =~ "ababcdcdabef" と同じ
- 例: /(ab)(cd)\2/ =~ "ababcdcdabef" # => 2
- /abcdcd/ =~ "ababcdcdabef" と同じ
- 例: /(ab(cd))\2/ =~ "ababcdcdabef" # => 2
- /abcdcd/ =~ "ababcdcdabef" と同じ
- 例: /(ab(cd))\1\2/ =~ "ababcdabcdcdabef" # => 2
- /abcdabcdcd/ =~ "ababcdabcdcdabef" と同じ
- * と *? 直前の表現の 0 回以上の繰り返し.* は,できるだけ長くマッチしようとし,*? はマッチする最短の文字列を探す.例えば,正規表現 /st.*ed/ 及び,/st.*?ed/ は,いずれも,st で始まり,任意の文字が 0 個以上続き,ed で終わる文字列にマッチする.しかし,以下の例に示すように,前者は,マッチするできるだけ長い文字列を探し,後者は,できるだけ短い文字列にマッチさせようとする.なお,以下の例は," " 内に記述した文字列の内,[ ] 内に与えた正規表現にマッチする部分を出力( p )したものである.
- 例: p "sted=stedabc"[/st.*ed/]
- "sted=sted" # => nil
- 例: p "sted=stedabc"[/st.*?ed/]
- "sted" # => nil
- 例: p "stabced=stabcedabc"[/st.*ed/]
- "stabced=stabced" # => nil
- 例: p "stabced=stabcedabc"[/st.*?ed/]
- "stabced" # => nil
- + と +? 直前の表現の 1 回以上の繰り返しであり,* と *? と,繰り返し回数を除けば,基本的に同じである.
- 例: p "sted=stedabc"[/st.+ed/]
- "sted=sted" # => nil
- 例: p "sted=stedabc"[/st.+?ed/]
- "sted=sted" # => nil
- 例: p "stabced=stabcedabc"[/st.+ed/]
- "stabced=stabced" # => nil
- 例: p "stabced=stabcedabc"[/st.+?ed/]
- "stabced" # => nil
- {m},{m,},及び,{m,n} 直前の表現の m 回,m 回以上,及び,m 回以上(最大 n 回)の繰り返し.できるだけ長くマッチしようとする( * 参照).
- 例: p "stabced=stabcedabc"[/st.{1}ed/]
- nil # => nil
- 例: p "stabced=stabcedabc"[/st.{1,}ed/]
- "stabced=stabced" # => nil
- 例: p "stabced=stabcedabc"[/st.{1,3}ed/]
- "stabced" # => nil
- {m}?,{m,}?,及び,{m,n}? 直前の表現の m 回,m 回以上,及び,m 回以上(最大 n 回)の繰り返し.マッチする最短の文字列を探す( *? 参照).
- 例: p "stabced=stabcedabc"[/st.{1}?ed/]
- nil # => nil
- 例: p "stabced=stabcedabc"[/st.{1,}?ed/]
- "stabced" # => nil
- 例: p "stabced=stabcedabc"[/st.{1,3}?ed/]
- "stabced" # => nil
- ? 直前の表現の 0,又は,1 回の繰り返し.
- 例: p "aasted"[/st.?ed/]
- "sted" # => nil
- 例: p "aastaed"[/st.?ed/]
- "staed" # => nil
- 例: p "aastabed"[/st.?ed/]
- nil # => nil
- ?? 直前の表現の 0,又は,1 回の繰り返し(最短一致).
- 例: p "aastabc"[/st.?/]
- "sta" # => nil
- 例: p "aastabc"[/st.??/]
- "st" # => nil
- | どちらか一方.
- 例: /aaa|bbb/ =~ "aacbbbcaaa" # => 3
- 例: /aa(c|b)bb/ =~ "aacbbbcaaa" # => 0
- (?= ) 先読み.(?=re1)re2 という表現は,re1 と re2 両方にマッチするものを意味し,また,re1(?=re2) という表現は,正規表現 re1 の後に re2 とマッチする文字列が続くということを意味する.
- 例 ( 3 文字で,かつ,a-c のいずれでもない文字列):
- p "abxycxyzaxa"[/(?=...)[^a-c][^a-c][^a-c]/]
- "xyz" # => nil
- /(?=...)[^a-c][^a-c][^a-c]/ =~ "abxycxyzaxa" # => 5
- 例 ( xyz の後に,a-c のいずれかが続く文字列):
- p "abxyzxcxyzaxa"[/xyz(?=[a-c])/]
- "xyz" # => nil
- /xyz(?=[a-c])/ =~ "abxyzxcxyzaxa" # => 7
- (?! ) 否定先読み.(?!re1)re2 という表現は,re1 にマッチしないが re2 にはマッチすることを意味する.
.
- 例 ( abc にマッチしない 3 文字の文字列):
- p "abcxyzaxa"[/(?!abc).../]
- "bcx" # => nil