# 正規表現

- 後方参照
- 文字クラス
- バックトラック
- サンプル

以下は、ruby がサポートする正規表現記号(メタ文字)の一覧です。

- \を伴わない英数字 はメタ文字ではない
- \を伴う記号 はメタ文字ではない(`\*'は「繰り返し」でなく「アステリスク」)

という規則があります。

以下の説明の中で「多バイト文字に対応した正規表現」とは、 $KCODE が設定されているか、あるいは明示的に漢字オプショ ン(正規表現リテラルを参照)を指定するなどにより多バイト文字 にマッチし得る正規表現を指します。

`^`

  行頭。文字列の先頭や改行文字の直後の位置にマッチします。

`$`

  行末。文字列の末尾や改行文字の直前の位置にマッチします。改行自身は含 みません。

  ruby 1.8 feature: 以前は、文字列末尾の改行に対して改行の前だけ にマッチしていましたが、常に文字列の末尾にもマッチするように変更され ました。trap::Regexp

      p "\n".gsub(/$/, "o")
      => "o\n"  (1.6)
      => "o\no" (1.8) # 改行文字の前と文字列末尾の前で1回ずつ

`.`

  改行を除く任意の 1 文字にマッチします。正規表現オプション m (複数行 モード。正規表現リテラルを参照)では、改行を含む任意の 1 文字にマッチします。

  多バイト文字に対応した正規表現では、その 1 文字(1 バイトでなく)とマッ チします。

      $KCODE = "sjis"          # 漢字コード指定、Unixなら"euc"
      p /..a./  =~ "あああaあ" # => 2 (文字列の3byte目からマッチ)
      p /..a./n =~ "あaあ"   # => 0 (一時的に漢字コードを"none"に指定)

  また、不完全な多バイト文字の一部(その文字だけでは多バイト文字かバイ ナリかASCIIか判断が付かない場合)とはマッチしません。

      p /./e =~ "あ"[0,1]     # => nil

`\w`

  英数字。`[0-9A-Za-z_]` と同じ。

  多バイト文字に対応した正規表現では、日本語のいわゆる全角文字にもマッ チします。`[0-9A-Za-z_０-９Ａ-Ｚａ-ｚ]` とでも言えましょうか。 *1

`\W`

  非英数字。`\w` 以外の一文字。

`\s`

  空白文字。`[ \t\n\r\f]` と同じ

`\S`

  非空白文字。`[ \t\n\r\f]` 以外の一文字。

`\d`

  数字。`[0-9]` と同じ。こちらはいわゆる全角文字には決してマッチしません。

`\D`

  非数字

`\A`

  文字列先頭。`^` とは異なり改行の有無には影響しません。

`\Z`

  文字列末尾。文字列が改行で終っていればその改行の直前にマッチします。

  ruby 1.8 feature: 以前は、文字列末尾の改行に対して改行の前だけ にマッチしていましたが、常に文字列の末尾にもマッチするように変更され ました。trap::Regexp

      p "\n".gsub(/\Z/, "o")
      => "o\n"   (1.6)
      => "o\no"  (1.8) # 改行文字の前と文字列末尾の前で1回ずつ

`\z`

  文字列末尾。`$` や `\Z` とは異なり改行の有無には影響しません。

`\b`

  文字クラス指定の外では語境界 (`\w` と `\W` のあいだにマッチ)。 文字クラス指定内ではバックスペース (0x08)。

`\B`

  非語境界

`\G`

  前回マッチした箇所(の直後)にマッチ (幅を持たない)。 初回だけは先頭位置にマッチします(\Aと同じ)。

  scan や、gsub で使用できます。前回マッチし た場所の後からマッチさせたい場合に使用します。

  簡単な(あまり役に立たない)例は以下。 *2

      # 先頭から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   =~ "スウプを一さじ"  # => nil (「スー」または「ウプ」)
      /スー|ウプ/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 両方にマッチするものにマッチする正規表現で す。

      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: /[^]/

先頭(あるいは否定の "^" の直後)にある "]" は、文字クラスの終りではなく "]" そのものを表します。 *3

    p /[]]/ =~ "]"       # => 0
    p /[^]]/ =~ "]"      # => nil

"^", "-", "]" そして "\\"(バックスラッシュ)は、バックスラッシュでエス ケープして、その文字にマッチさせることができます。

    p /[\^]/ =~ "^"   # => 0
    p /[\-]/ =~ "-"   # => 0
    p /[\]]/ =~ "]"   # => 0
    p /[\\]/ =~ "\\"  # => 0

[] 内には文字列と同じバックスラッシュ記法と、 正規表現 \w, \W, \s, \S, \d, \D (これらは文字クラスの略記法です)が 使用できます。 *4

否定による以下のような文字クラスは改行文字にもマッチすることに 注意してください(正規表現 \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 =~ "Ａ"        # => nil

## バックトラック

*5

`(?> )` という特殊な括弧で正規表現をかこむと、その括弧の中の表現に マッチした部分ではバックトラックが起こりません。その意味を例を挙げて 見てみます。

例えば通常の正規表現では

p /(a*)ab/ === 'aaab'

はマッチします。その過程は以下のようになります。

1. 正規表現 `a*` がインデックス 0 で `a` みっつにマッチする
2. 正規表現 `a` がマッチに失敗
3. 正規表現 `a*` がマッチした分を少し「あきらめさせて」、 `a` ふたつにマッチさせる (バックトラックする)
4. 正規表現 `a` が `a` にマッチする
5. 正規表現 `b` が `b` にマッチする

しかしこの正規表現の括弧を `(?> )` に変えるとマッチしなくなります。 その過程は以下のようになります。

1. 正規表現 `a*` がインデックス 0 で `a` みっつにマッチする
2. 正規表現 `a` がマッチに失敗
3. `a*` がマッチした分をすこし減らして試したいが、 抑止指定されているのですぐに失敗する
4. 正規表現 `a*` がインデックス 1 で `a` ふたつにマッチする

以下同じように失敗して、最終的にマッチ全体が失敗します。

ひらたく言うと、通常の正規表現の基本が「欲張りマッチ」なのに対して、 `(?> )` は一回取ったものは絶対に離さない「超欲張りマッチ」を行います。

## サンプル

*6

ここにあげるサンプルは流用しやすいように `$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 *7が必要)

      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,345 Hz"

*1 [2004-10-22] それじゃ、ひらがな、カタカナ、漢字は含まれていないってことにならない？ 実際は含むよね？ /[0-9A-Za-z_０-９Ａ-Ｚａ-ｚ]/e =~ 'あ' # => nil, /\w/e =~ 'あ' # => 0
*2 より良い例があれば、書き換えてください。役に立つ。わかりやすい が原則
*3 ruby 1.8 feature このような "]" は、バックスラッシュエスケー プを行うことが推奨されます。ruby 1.8 では、エスケープしない "[" や "]" に対して警告が出るようになりました。
*4 文字クラスの中では . や * はバックスラッシュでエスケープする 必要はありません。(しても構いません。)
*5[ruby-list:28084] 以下のスレッドも参照してください。
*6 このサンプルは「詳説正規表現第二版」から引用あるいは参考にさせて頂いた
*7 Oniguruma は小迫氏が開発している正規表現ライブラリで、 将来 Ruby の正規表現エンジンになる予定で 1.9.0 には既に取り込まれています。 <URL:ftp://ftp.ruby-lang.org/pub/ruby/contrib/>onigd* か、 CVS [ruby-cvs:oniguruma] から入手できる。Oniguruma の正規表現については [ruby-cvs:oniguruma/doc/RE]を参照。 <URL:http://www.geocities.jp/kosako3/oniguruma/>

links: [String] [manual page] [ruby 1.8 feature] [trap::Regexp] [リテラル] [正規表現] [組み込み変数]
reverse links: [1.6.8から1.8.0への変更点(まとめ)] [Regexp] [Rubyリファレンスマニュアル] [ruby 1.8 feature] [scanf.rb] [リテラル]