正規表現
正規表現に関してはリテラル/正規表現リテラル 、$&、 Regexp そして MatchData なども参照して下さい。
正規表現記号
以下は、ruby がサポートする正規表現記号(メタ文字)の一覧です。 (正規表現のオプションについてはリテラル/正規表現リテラル を参照してください)
- \を伴わない英数字 はメタ文字ではない
- \を伴う記号 はメタ文字ではない(`\*'は「繰り返し」でなく「アスタリスク」)
という規則があります。
- ^
-
行頭。文字列の先頭や改行文字の直後の位置にマッチします。
- $
-
行末。文字列の末尾や改行文字の直前の位置にマッチします。改行自身は含 みません。
- .
-
改行を除く任意の 1 文字にマッチします。正規表現オプション m (複数行 モード。リテラル/正規表現リテラル を参照)では、改行を含む任意の 1 文字にマッチします。
- \w
-
英数字。[0-9A-Za-z_] と同じ。
- \W
-
非英数字。\w 以外の一文字。
- \s
-
空白文字。[ \t\n\r\f] と同じ
- \S
-
非空白文字。[ \t\n\r\f] 以外の一文字。
- \d
-
数字。[0-9] と同じ。こちらはいわゆる全角文字には決してマッチしません。
- \D
-
非数字
- \A
-
文字列先頭。^ とは異なり改行の有無には影響しません。
- \Z
-
文字列末尾。文字列が改行で終っていればその改行の直前にマッチします。
- \z
-
文字列末尾。$ や \Z とは異なり改行の有無には影響しません。
- \b
-
文字クラス指定の外では語境界 (\w と \W のあいだにマッチ)。 文字クラス指定内ではバックスペース (0x08)。
- \B
-
非語境界
- \G
-
前回マッチした箇所(の直後)にマッチ (幅を持たない)。 初回だけは先頭位置にマッチします(\Aと同じ)。
String#scan や、String#gsub で使用できます。前回マッチし た場所の後からマッチさせたい場合に使用します。
簡単な(あまり役に立たない)例は以下。
# 先頭から3桁ずつの数値を(数値が続く限り)取り出す。 str = "123456 789" str.scan(/\G\d\d\d/) {|m| p m }
- [ ]
-
文字クラス指定。文字クラス を参照。
- *
-
直前の表現の 0 回以上の繰り返し。できるだけ長くマッチしようとする。
- *?
-
量指定子(quantifiers)。 直前の表現の 0 回以上の繰り返し (最短一致)
orig_str = "<b>Ruby</b> and <b>Perl</b>" p orig_str.gsub(/<b>(.*)<\/b>/, '<em>\1</em>') # => "<em>Ruby</b> and <b>Perl</em>" p orig_str.gsub(/<b>(.*?)<\/b>/, '<em>\1</em>') # => "<em>Ruby</em> and <em>Perl</em>"
- +
-
量指定子(quantifiers)。 直前の表現の 1 回以上の繰り返し
- +?
-
量指定子(quantifiers)。 直前の表現の 1 回以上の繰り返し (最短一致)
- {m}
- {m,}
- {m,n}
-
範囲指定繰り返し制御(interval quantifier)。 それぞれ直前の正規表現の * m 回 * m 回以上 * m 回以上、最大 n 回 の繰り返し。{,n} や、{,} に対するマッチは必ず失敗する。
str = "foofoofoo" p str[/(foo){1}/] # => "foo" p str[/(foo){2,}/] # => "foofoofoo" p str[/(foo){1,2}/] # => "foofoo"
正規表現 ?, *, + はそれぞれ {0,1}, {0,} {1,} と同じです。
- {m}?
- {m,}?
- {m,n}?
-
範囲指定繰り返し制御(interval quantifier)。 それぞれ直前の正規表現の * m 回 * m 回以上 * m 回以上、最大 n 回 の繰り返し(最短一致)。
- ?
-
量指定子(quantifiers)。 直前の正規表現の 0 または 1 回の繰り返し。
p /プリンター?は/s =~ "プリンタは" # => 0 (0文字目からマッチ) p /プリンター?は/s =~ "プリンターは" # => 0 p /プリンター?は/s =~ "プリンターーは" # => nil
- ??
-
量指定子(quantifiers)。 直前の正規表現の 0 または 1 回の繰り返し(最短一致)
- |
-
選択(alternative)。優先順位が低いので下の「グループ化」とあわせて使うことが多い。
/ス(ー|ウ)プ/s =~ "スウプを一さじ" # => 0 (0文字目からマッチ) /ス(ー|ウ)プ/s =~ "スープレックス" # => 0 /スー|ウプ/s =~ "スウプを一さじ" # => 2 (「スー」または「ウプ」) /スー|ウプ/s =~ "スープレックス" # => 0
- ( )
-
正規表現のグループ化。括弧の中の正規表現にマッチした文字列は後方参照 のために記憶されます。
- \1, \2 ... \n
-
後方参照(back reference)。後方参照 を参照。
- (?# )
-
コメント。括弧の中の任意の文字列は無視されます。
- (?: )
-
後方参照を伴わないグループ化。つまり、\1, \2 (あるいは、 $1, $2)などの対象にはならず、 単純なグループ化の用途で使用します。
/(abc)/ =~ "abc" p $1 => "abc" /(?:abc)/ =~ "abc" p $1 => nil
- (?= )
-
先読み(lookahead)。 パターンによる位置指定(幅を持たない)
(?=re1)re2
という表現は、re1 と re2 両方にマッチするものにマッチする正規表現です。(使用例 [ruby-list:46929])
# 「 3 文字目から 5 文字目の間に 3 を含んでいる 8 文字の数字列を抜き出す」 re = /((?=\d{2,4}3)\d{8})/ re =~ "asdf1234567890" # => 4 $& # => "12345678" re =~ "asdf234567890" # => nil re =~ "asdf1111234567890" # => 5 $& # => "11123456" re =~ "asdf111112345xxxx" # => nil
re1(?=re2)
という表現は、後に re2 とマッチする文字列が続く、正規表現 re1 です。
p /foo(?=bar)/ =~ "foobar" # => 0 p $& # => "foo" (bar の部分の情報はない)
- (?! )
-
否定先読み(negative lookahead)。 パターンの否定による位置指定(幅を持たない)
(?!re1)re2
という表現は、re1 にマッチしないが re2 にはマッチする正規表現です。
# 000 を除く 3 桁の数字 re = /(?!000)\d\d\d/ p re =~ "000" # => nil p re =~ "012" # => 0 p re =~ "123" # => 0 # C 言語の識別子 ([A-Za-z_] で始まり、[0-9A-Za-z_] が続く文字列) /\b(?![0-9])\w+\b/
- (?> )
-
バックトラック を抑止する。
この表現はまだ試験実装中です。将来なくなる可能性もありますので、 そのつもりで使ってください。特に汎用ライブラリなどで使ってはいけません。
- (?ixm-ixm)
-
正規表現中でのiオプション、xオプション、mオプションのon/off。オプショ ンについてはリテラル/正規表現リテラル を参照。
re = /A(?i)a(?-i)A/ p re =~ "AaA" # => 0 p re =~ "AAA" # => 0 p re =~ "AAa" # => nil
- (?ixm-ixm: )
-
括弧内のiオプション、xオプション、mオプションのon/off。括弧の範囲内 で設定
re = /A(?i:a)A/ p re =~ "AaA" # => 0 p re =~ "AAA" # => 0 p re =~ "AAa" # => nil
後方参照
正規表現 \1 \2 ... \n は、後方参照です。n 番目の括弧(正規 表現 ( ) グルーピング)にマッチした文字列にマッチします。
/((foo)bar)\1\2/
は、
/((foo)bar)foobarfoo/
と同じです。
例:
re = /(foo|bar|baz)\1/ p re =~ 'foofoo' # => 0 p re =~ 'barbar' # => 0 p re =~ 'bazbaz' # => 0 p re =~ 'foobar' # => nil
対応する括弧は、後方参照よりも左側にないといけません。
対応する括弧の中に後方参照があれば常にマッチに失敗します。 また、対応する括弧がない 1 桁の後方参照も常にマッチに失敗します。
p /(\1)/ =~ "foofoofoo" # => nil p /(foo)\2/ =~ "foo\2" # => nil
2 桁以上の後方参照も指定できますが、バックスラッシュ記法 の \nnn (8進 nnn に対応する文字)と混同しないように注意する必要が あります。数値が 1 桁なら常に後方参照です。2 桁以上の指定では、対応す る括弧がなければ 8 進コードと見なされます。
また、逆に正規表現中に 8 進で 1 桁のコードを記述するには \01 など 0 で 始める必要があります(\0 という後方参照はないので曖昧になりません)。
p /\1/ =~ "\1" # => nil # 対応する括弧のない後方参照 p /\01/ =~ "\1" # => 0 8 進コード p /\11/ =~ "\11" # => 0 8 進コード # 8 進コード (対応する括弧がないので) p /(.)\10/ =~ "1\10" # => 0 # 後方参照 (対応する括弧があるので) p /((((((((((.))))))))))\10/ =~ "aa" # => 0 # 8 進コード(ただし、"\0" + "8" になっている # \08 という 8 進コードはないので) p /(.)\08/ =~ "1\0008" # => 0 # 後方参照に続けて数字を書きたいなら括弧でグループ化して区切る # などするしかない。 p /(.)(\1)1/ =~ "111" # => 0
文字クラス
正規表現 [ ] は、文字クラス指定です。[] 内に列挙したいずれかの一 文字にマッチします。
例えば、/[abc]/ は、"a", "b", "c" いずれか一文字にマッチします。 ASCIIコード順で連続する文字列は間に `-' を置いて /[a-c]/ のように書 くこともできます。また、先頭が `^' であれば指定した文字以外の一文字 とマッチします。
先頭以外にある `^' はその文字そのものとマッチします。また、先頭、末尾 にある `-' は、その文字そのものとマッチします。
p /[a^]/ =~ "^" # => 0 p /[-a]/ =~ "-" # => 0 p /[a-]/ =~ "-" # => 0 p /[-]/ =~ "-" # => 0
空の文字クラスはエラーになります。
p /[]/ =~ "" p /[^]/ =~ "^" # => invalid regular expression; empty character class: /[^]/
先頭(あるいは否定の "^" の直後)にある "]" は、文字クラスの終りではなく "]" そのものを表します。 このような "]" は、バックスラッシュエスケープを行うことが推奨されます。 エスケープしない "[" や "]" に対して警告が出るようになりました。
p /[]]/ =~ "]" # => 0 p /[^]]/ =~ "]" # => nil
"^", "-", "]" そして "\\"(バックスラッシュ)は、バックスラッシュでエス ケープして、その文字にマッチさせることができます。
p /[\^]/ =~ "^" # => 0 p /[\-]/ =~ "-" # => 0 p /[\]]/ =~ "]" # => 0 p /[\\]/ =~ "\\" # => 0
[] 内には文字列と同じバックスラッシュ記法と、 正規表現 \w, \W, \s, \S, \d, \D (これらは文字クラスの略記法です)が 使用できます。
文字クラスの中では . や * はバックスラッシュでエスケープする 必要はありません(しても構いません)。
否定による以下のような文字クラスは改行文字にもマッチすることに 注意してください(正規表現 \W,\D も同様)。
p /[^a-z]/ =~ "\n" # => 0
文字クラスの中では以下の特殊な指定が使用できますが、この機能は将来に渡っ てサポートされるとは約束されていません(なのでここでは詳細は書きません 詳細を知りたい方は grep(1) 等のマニュアルを参照して ください)。
[:alnum:] 数字とアルファベット 0-9a-zA-Z [:alpha:] アルファベット a-zA-Z [:blank:] 空白類 [:cntrl:] コントロール文字 [:digit:] 数字 [:graph:] 空白を除く印字可能な可視文字 [:lower:] 小文字 [:print:] 可視文字 [:punct:] 記号 [:space:] 空白文字 [:upper:] 大文字 [:xdigit:] 16進文字
例: ("[]" を含めて "[:...:]" が1文字を表していることに注意。 文字クラスの "[]" ではない)
p /[[:alnum:]][[:cntrl:]]/ =~ "a\x01" # => 0
注: 全角文字は考慮されません。正規表現が漢字にマッチするように指定さ れていても [:alpha:] などは、全角のアルファベットとはマッチしません。
p /[[:alpha:]]/e =~ "A" # => nil
バックトラック
(?> ) という特殊な括弧で正規表現をかこむと、その括弧の中の表現に マッチした部分ではバックトラックが起こりません。その意味を例を挙げて 見てみます。
例えば通常の正規表現では
p /(a*)ab/ === 'aaab'
はマッチします。その過程は以下のようになります。
- 正規表現 a* がインデックス 0 で a みっつにマッチする
- 正規表現 a がマッチに失敗
- 正規表現 a* がマッチした分を少し「あきらめさせて」、 a ふたつにマッチさせる (バックトラックする)
- 正規表現 a が a にマッチする
- 正規表現 b が b にマッチする
しかしこの正規表現の括弧を (?> ) に変えるとマッチしなくなります。 その過程は以下のようになります。
- 正規表現 a* がインデックス 0 で a みっつにマッチする
- 正規表現 a がマッチに失敗
- a* がマッチした分をすこし減らして試したいが、 抑止指定されているのですぐに失敗する
- 正規表現 a* がインデックス 1 で a ふたつにマッチする
以下同じように失敗して、最終的にマッチ全体が失敗します。
ひらたく言うと、通常の正規表現の基本が「欲張りマッチ」なのに対して、 (?> ) は一回取ったものは絶対に離さない「超欲張りマッチ」を行います。
サンプル
ここにあげるサンプルは流用しやすいように $re_ で始まるグローバル 変数に設定することにしている。
数値
浮動小数点数(整数も含む)
$re_float = /[-+]?(?:[0-9]+(\.[0-9]*)?|(\.[0-9]+))([eE][-+]?[0-9]+)?/ p $re_float =~ "1.23" # => 0 p $&.to_f # => 1.23 p $re_float =~ ".23" # => 0 p $&.to_f # => 0.23 p $re_float =~ "1.23e1" # => 0 p $&.to_f # => 12.3 p $re_float =~ "1.23e-1" # => 0 p $&.to_f # => 0.123
数字を 3 桁ずつコンマで区切る
方法1: 戻り読みと先読みを利用する方法 (戻り読み(lookbehind)は Oniguruma が必要)
p "tone of 12345Hz".gsub(/(?<=\d)(?=(?:\d\d\d)+(?!\d))/, ',') => ruby 1.8.0 (2003-08-07) [i586-linux] "tone of 12,345Hz"
方法2: 先読みだけを利用する方法
p "tone of 12345Hz".gsub(/(\d)(?=(?:\d\d\d)+(?!\d))/, '\1,') => ruby 1.8.0 (2003-08-07) [i586-linux] "tone of 12,345Hz"
方法3: 先読みも利用しない方法
s = "tone of 12345Hz" nil while s.gsub!(/(.*\d)(\d\d\d)/, '\1,\2') p s => ruby 1.8.0 (2003-08-07) [i586-linux] "tone of 12,345Hz"