【Ruby】正規表現早見表 by GPT-o1

勉強用で早見表をGPT-o1さんに作成してもらいました。

:::note info
間違っている箇所がありましたら、ご指摘ください...！
:::

# Ruby 正規表現早見表

以下は、Rubyの正規表現（Regexp）を利用する際の代表的な構文・機能をまとめた早見表です。RubyはPerl由来の正規表現エンジンを用いており、多くのPerl互換正規表現構文が利用可能です。また、Ruby独自の拡張や機能も存在します。

---

## 基本構文

| パターン | 意味 | 例 |
|----------|------|----|
| `.` | 任意の1文字（改行を除く） | `a.b`は「a」と「b」の間に1文字あるものにマッチ |
| `^` | 行頭を意味するアンカー | `^abc`は行頭が「abc」で始まる行にマッチ |
| `$` | 行末を意味するアンカー | `abc$`は行末が「abc」で終わるにマッチ |
| `\A` | 文字列の先頭にマッチ | `\Aabc`は文字列の先頭が「abc」で始まる場合にマッチ |
| `\z` | 文字列の末尾（終端）にマッチ | `abc\z`は文字列の終端が「abc」で終わる場合にマッチ |
| `\Z` | 文字列の末尾（改行手前）にマッチ | `abc\Z`は末尾が「abc」または「abc\n」の場合にマッチ |
| `\b` | 単語境界（`\w`と`\W`の境界） | `\bword\b`は単語「word」単独にマッチ |
| `\B` | 非単語境界 | `\Babc`は単語境界ではない位置での「abc」にマッチ |

---

## 文字クラス

| クラス | 意味 | 例 |
|--------|------|----|
| `[abc]` | `a`または`b`または`c`のいずれか1文字 | `[abc]`は`a`か`b`か`c` |
| `[^abc]` | `a`でも`b`でも`c`でもない任意の1文字 | `[^0-9]`は数字以外の1文字 |
| `[a-z]` | `a`から`z`までのいずれか1文字 | `[A-Z]`は大文字アルファベット |
| `\d` | `[0-9]` (数字) | `\d\d`は2桁の数字 |
| `\D` | `[^0-9]` (数字以外) | `\D`は数字以外1文字 |
| `\w` | `[0-9A-Za-z_]` (単語構成文字) | `\w+`は1文字以上の英数字アンダースコア列 |
| `\W` | `[^0-9A-Za-z_]` (非単語構成文字) | `\W`は英数字以外の1文字 |
| `\s` | 空白文字 `[ \t\r\n\f]` | `\s*`は0回以上の空白 |
| `\S` | 非空白文字 | `\S+`は空白以外の1文字以上 |

---

## 繰り返し・量指定子

| パターン | 意味 | 例 |
|----------|------|----|
| `*` | 直前のパターン0回以上の繰り返し | `a*`は「","","a","aa","aaa",...|
| `+` | 直前のパターン1回以上の繰り返し | `a+`は「a」「aa」「aaa」...|
| `?` | 直前のパターン0回または1回 | `colou?r`は「color」または「colour」にマッチ |
| `{n}` | 直前のパターンをn回繰り返し | `a{3}`は「aaa」にマッチ |
| `{n,}` | n回以上繰り返し | `a{2,}`は「aa」「aaa」...|
| `{n,m}` | n回以上m回以下繰り返し | `a{2,4}`は「aa」「aaa」「aaaa」にマッチ |

※デフォルトはグリーディ(貪欲)マッチ。非貪欲(最短)マッチには量指定子の後に`?`を付ける。例:`a+?`、`a*?`など。

---

## グルーピング・後方参照

| パターン | 意味 | 例 |
|----------|------|----|
| `(abc)` | グループ化・キャプチャ | `(abc)+`は「abc」「abcabc」「abcabcabc」... |
| `(?:abc)` | グループ化のみ（キャプチャしない） | `(?:abc){2}`は「abcabc」にマッチ |
| `(?<name>abc)` | 名前付きキャプチャ | `(?<word>\w+)`で`\k<word>`で参照可能 |
| `\1`、`\2`... | キャプチャ済みグループの後方参照 | `(abc)\1`は「abcabc」にマッチ |
| `\k<name>` | 名前付きキャプチャの後方参照 | `(?<d>\d{2})-\k<d>`は「12-12」などにマッチ |

---

## オプション・フラグ

正規表現リテラル `/pattern/` の末尾にフラグを付与することで動作を変更できます。  
`Regexp.new("pattern", option)`や`%r{pattern}i`のような記法も利用可能。

| オプション | 意味 | 例 |
|------------|------|----|
| `i` | 大文字小文字を無視する (ignore case) | `/abc/i`は「ABC」「AbC」等にもマッチ |
| `m` | `.`が改行文字にもマッチする(dot matches newline) | `/abc.*def/m`は複数行にまたがるマッチを許可 |
| `x` | 正規表現内で空白やコメントを無視（可読性向上） | `/a b c/x`は実質`/abc/`と同等 |
| `o` | 正規表現リテラルのコンパイルを一回のみ実行 | `/#{some_var}/o`など |

---

## 特殊構文

| 構文 | 意味 | 例 |
|------|------|----|
| `(?=pattern)` | 正先読み(Positive look-ahead) ：`pattern`にマッチするかを確認、消費しない | `\d+(?=円)`は「円」の前にある数字をマッチ |
| `(?!pattern)` | 負先読み(Negative look-ahead) ：`pattern`にマッチしない場合にマッチ | `foo(?!bar)`は「foobar」を除く「foo...」にマッチ |
| `(?<=pattern)` | 正後読み(Positive look-behind)：`pattern`にマッチした直後位置から検索（固定幅のみ） | `(?<=\$)\d+`は「$」の後に続く数字列 |
| `(?<!pattern)` | 負後読み(Negative look-behind)：`pattern`にマッチしない場合にマッチ（固定幅のみ） | `(?<!\$)\d+`は「$」が直前にない数字にマッチ |

---

## Ruby固有の点

- `=~`演算子や`match?`メソッドで文字列と正規表現をマッチング可能。  
  ```ruby
  if "hello" =~ /ell/
    puts $~ # => #<MatchData "ell">
  end

  "hello".match?(/ell/) # => true (Ruby 2.4+)
  ```
- `MatchData`オブジェクトを利用するとキャプチャ済みの文字列にアクセス可能。  
  ```ruby
  m = "Price: 100 yen" =~ /(\d+) yen/
  $1 # => "100"
  
  # もしくは
  mdata = "Price: 100 yen".match(/(?<price>\d+) yen/)
  mdata[:price] # => "100"
  ```

- `String#gsub`や`String#sub`で正規表現を利用した置換が可能。  
  ```ruby
  "hello".gsub(/[aeiou]/, '*') # => "h*ll*"
  
  "2024-12-14".sub(/(\d+)-(\d+)-(\d+)/, '\3/\2/\1') # => "14/12/2024"
  ```

---

## まとめ

- Rubyの正規表現はPerl互換で豊富な機能を持つ。
- `^`や`$`、`\A`、`\z`などを用いたアンカーや、`\d`、`\w`などのショートハンドで効率的なマッチを行える。
- `( ... )`や`(?<name> ... )`でキャプチャを行い、`$1`や`\k<name>`で結果を利用可能。
- 量指定子や先読み・後読みを活用して高度なパターン抽出が可能。
- オプション（`i`, `m`, `x`, `o`）を使い分けてマッチング条件を柔軟に変更できる。

## 正規表現確認スクリプトを作成しました。

以下、ご自由にコピペしてお使いください。

```rb
# ruby test_regex.rb

# 以下のコードは各パターンが動作しているか確認するサンプルです。

# The code snippet you provided is a Ruby script that tests various regular expression patterns
# against a set of test texts. Here's a breakdown of what the code does:

TEST_TEXTS = [
  "abc",
  "abc\n",
  "abcd",
  "Price: 100 yen",
  "color", "colour",
  "hello",
  "foo", "foobar",
  "foo\nbar",
  "2024-12-14",
  "abc def",
  "$250",
  "12-12"
]

PATTERNS = [
  /a.b/,
  /^abc/,
  /abc$/,
  /\Aabc/,
  /abc\z/,
  /abc\Z/,
  /\bword\b/,
  /\Babc/,
  /[abc]/,
  /[^abc]/,
  /[0-9]/,
  /\d\d/,
  /\D/,
  /\w+/,
  /\W/,
  /\s*/,
  /\S+/,
  /a*/,
  /a+/,
  /colou?r/,
  /a{3}/,
  /a{2,}/,
  /a{2,4}/,
  /(abc)+/,
  /(?:abc){2}/,
  /(?<word>\w+)/,
  /(?<d>\d{2})-\k<d>/,
  /\d+(?=円)/,
  /foo(?!bar)/,
  /(?<=\$)\d+/,
  /(?<!\$)\d+/
]

PATTERNS.each do |pat|
  puts "Pattern: #{pat}"
  TEST_TEXTS.each do |text|
    puts "  '#{text}' => #{text.match?(pat)}"
  end
  puts
end
```