Rubyの正規表現の使い方をマスターしよう!match/gsub

Rubyの正規表現の使い方をマスターしよう!match/gsub

正規表現とは

正規表現とは、メタ文字と呼ばれる記号と文字列を組み合わせた構文のことで、検索対象となる文章中から任意の文字列パターンを検索することができます。

そこで、今日はRubyで利用できる代表的な正規表現について、わかりやすく解説していきます。 image

目次
  1. Regexpクラス
  2. matchメソッド
  3. 正規表現オブジェクトを生成
  4. ①文字列"パターン"に対して検索を行います
  5. ②文字列"パティーン"に対して検索を行います
  6. matchメソッド(Stringクラス)
  7. 正規表現を使った文字列の操作
  8. subメソッド
  9. gsubメソッド
  10. メタ文字とは
  11. メタ文字を利用しよう!
  12. 正規表現クイズ 第1問
  13. 正規表現クイズ 第2問
  14. 正規表現クイズ 第3問
  15. 正規表現クイズ 第4問
  16. 正規表現クイズ 第5問
  17. 正規表現クイズ 第6問
  18. 正規表現クイズ 第7問
  19. 正規表現クイズ 第8問
  20. 正規表現クイズ 第9問
  21. 正規表現クイズ 第10問
  22. 正規表現クイズ 第11問
  23. 正規表現クイズ 第12問
  24. まとめ

Regexpクラス

Rubyにおいて、正規表現を利用する際に利用するオブジェクトは Regexp というクラスです。 正規表現はRegexpクラスのメソッドを用いることで実現することができます。 まずは、Regexpクラスをnewメソッドを利用し、簡単に解説を行います。

Regexp.new("文字列")

上記はRegexpオブジェクトを生成する処理ですが、引数に"文字列"を与えています。これにより、正規表現のパターンとして"文字列"というパターンが作成されます。

これは下記のように表すことができます。

/文字列/

シングルクォーテーション、またはダブルクォーテーションで囲まれているものをプログラム中で文字列として認識しますが、スラッシュで囲まれているものをプログラム中では正規表現を表します。

また、Regexpクラスのnewメソッドは引数を複数指定することができます。

Regexp.new("文字列", Regexp::IGNORECASE)  → 文字の大小の違いを無視します
Regexp.new("文字列", Regexp::MULTILINE)      → 複数行の文字列に対応します

これらはそれぞれ下記のように表すことができます。

/文字列/i
/文字列/m

このようにRegexpクラスのnewメソッドを使用することで、正規表現オブジェクトを生成することができます。

matchメソッド

Regexpクラスのnewメソッドで生成された正規表現オブジェクトはmatchメソッドを利用することで文字列中のパターン検索を行うことができます。

# 正規表現オブジェクトを生成
reg = Regexp.new("パターン")

# ①文字列"パターン"に対して検索を行います
matched = reg.match("パターン")

# ②文字列"パティーン"に対して検索を行います
matched = reg.match("パティーン")

上記の①では"パターン"という文字列に対して検索を行い、マッチした結果を変数matchedに代入しています。 上記②では、"パティーン"という文字列に対して検索を行っています。

①は"パターン"という文字列にマッチするためmatchedには検索結果が代入されます。 ②は"パティーン"という文字列はマッチしないので、matchedはnilになります。

上記を応用することで、下記のようにif文で条件分岐を行うことができます。

reg = Regexp.new("パターン")
if reg.match("パターン")
  p 'マッチしました!'
end

そして上記は下記に書き換えることが可能です。

if 'パターン'  =~ /パターン/
  p 'パターンマッチしました!'
end

ここで =~ という記号が初めて登場しましたが、Rubyの演算子まとめ!Rubyの演算子をマスターしよう!でも紹介しているように、正規表現のパターンとマッチしているかどうかを判定する演算子になります。

文字列である'パターン'と正規表現の/パターン/がマッチしていればtrueしていなければfalseになるので、上記のプログラムの場合はtrueとなりif文内の処理が実行されます。

matchメソッド(Stringクラス)

ここまでに紹介したmatchメソッドはRegexpクラスのmatchメソッドでしたが、ここで紹介するのはString(文字列)クラスのmatchメソッドです。 使い方としてはRegexpクラスの時とほぼ同様になります。

"コーヒー牛乳が飲みたい".match(/牛乳/)

上記は文字列"コーヒー牛乳が飲みたい"に対して、正規表現/牛乳/というパターンで検索し、その結果を確認することができます。

もちろんif文でも利用可能です

if "コーヒー牛乳が飲みたい".match(/牛乳/)
  p "パターンマッチしました!"
end

また、下記のように書き換えることが可能です。(この場合はStringクラスのmatchメソッドではなく、正規表現のパターンマッチを判定する演算子を利用しています。)

if "コーヒー牛乳が飲みたい" =~ /牛乳/
  p "パターンマッチしました!"
end

このように、Regexp(正規表現)クラスやString(文字列)クラスにはmatchメソッド等の正規表現とのパターンマッチを行うメソッドが用意されています。

正規表現を使った文字列の操作

正規表現のパターンマッチを応用することで、文字列の検索だけではなく文字列に対して置換を行うことができます。

subメソッド

string.sub(pattern, replace)

正規表現のパターン(pattern)にマッチした最初の部分を文字列(replace)に置換します。

利用例としては、下記のようになります。

"コーヒー牛乳が飲みたい".sub(/コーヒー/, 'いちご')

結果

"いちご牛乳が飲みたい"

gsubメソッド

string.sub(pattern, replace)

正規表現のパターン(pattern)にマッチした部分全てを文字列(replace)に置換します。

利用例としては、下記のようになります。

"たけやぶにたけたてかけた".gsub(/たけ/, '竹')

結果

"竹やぶに竹たてかけた"

上記のようにパターンマッチした部分が2つ以上ある場合でも全て置換することができます。

メタ文字とは

正規表現では、メタ文字(特別な意味を持つ文字列)を使用して、検索する文字列のパターンを指定します。以下はよく利用されるメタ文字の例です。

メタ文字例

メタ文字 説明
. 改行を除く任意の1文字
* 直前のパターンの0回以上の繰り返し
+ 直前のパターンの1回以上の繰り返し
? 直前のパターンの0回または1回の繰り返し
[] []内のいずれかの1文字
{n} 直前のパターンがn回連続する
¥n 改行
¥d 数字1文字
^ 先頭から
$ 末尾から
選択(or)
() グループ化

メタ文字の[]に囲まれた中でだけ意味をもつ記号があります。

メタ文字[]で意味を持つ記号

メタ文字 説明
- 範囲を指定
^ 以外にマッチ

ある特定の文字を意味する正規表現

メタ文字 説明
\t タブ文字(ハードタブ)を表します
\r キャリッジリターン(CR)を表します
\n 改行文字(LF)を表します
\s 半角スペースを表します
\xXX コードXX(16進数2桁)の文字を表します

正規表現例

パターン 説明
[5] 数字の5に一致
[78] 数字の7又は8いずれかに一致
[1-3] 数字の1から3のいずれかに一致
[0-9] 数字に一致 ※¥dと同じ
[a-z] 小文字のアルファベットに一致
[A-Z] 大文字のアルファベットに一致
[^5] 数字の5以外に一致
[^0-9] 数字以外に一致
[^a-z] 小文字のアルファベット以外に一致

メタ文字の説明を見ただけでは正規表現の実感が掴めないと思いますので、以下にいくつか例を示します。

Windows 又は Macを表します。

Windows|Mac

windows 又は Windowsを表します。

[wW]indows

3桁の数字(123, 001, 951など)を表します。

[0-9]{3}

頭が1の4桁又は5桁の数字(12345, 1001, 1951など)を表します。

[1][0-9]{3,4}

頭が大文字アルファベットの1文字以上のアルファベット (A, Mac, MAC, ToSなど)を表します。

[A-Z][a-zA-Z]*

<から>まで、間に1文字以上の文字がある文字列を表します。

<.+?>

このように正規表現を利用することで、複数の文字列を1つで表現することができます。

メタ文字を利用しよう!

これまで紹介したメタ文字と、Rubyでの正規表現を使い、クイズ形式でパターンマッチを行ってみましょう。

正規表現クイズ 第1問

基本的な正規表現であり、|(パイプ)を利用し、どちらかに一致すればtrueとなる問題です。今回のケースだとマッチするでしょうか?

str = "Machintosh"
if str =~ /Windows|Mac/
  p "マッチしました"
else
  p "マッチしませんでした"
end

解答

"マッチしました"

正規表現クイズ 第2問

括弧( [] )で囲むことで、いずれかの文字と一致すればtrueとなります。今回のケースだとマッチするでしょうか?

str = "wWindows"
if str =~ /[wW]indows/
  p "マッチしました"
else
  p "マッチしませんでした"
end

解答

"マッチしました"

正規表現クイズ 第3問

変数strに代入された文字列"[wW]indows"、今回のケースだとマッチするでしょうか?

str = "[wW]indows"
if str =~ /[wW]indows/
  p "マッチしました"
else
  p "マッチしませんでした"
end

解答

"マッチしませんでした"

正規表現クイズ 第4問

このあたりから徐々に難しくなってきます。 括弧( [] )と、{}の組み合わせです。今回のケースだとマッチするでしょうか?

str = "0120"
if str =~ /[0-9]{3}/
  p "マッチしました"
else
  p "マッチしませんでした"
end

解答

"マッチしました"

正規表現クイズ 第5問

2桁の数値03、今回のケースだとマッチするでしょうか?

str = "03"
if str =~ /[0-9]{3}/
  p "マッチしました"
else
  p "マッチしませんでした"
end

解答

"マッチしませんでした"

正規表現クイズ 第6問

このあたりから少し複雑になってきますね。 5桁の数値12345、今回のケースだとマッチするでしょうか?

str = "12345"
if str =~ /[1][0-9]{3,4}/
  p "マッチしました"
else
  p "マッチしませんでした"
end

解答

"マッチしました"

正規表現クイズ 第7問

5桁の数値と文字列の組み合わせです。今回のケースだとマッチするでしょうか?

str = "1abcd"
if str =~ /1[a-zA-Z]{3,4}/
  p "マッチしました"
else
  p "マッチしませんでした"
end

解答

"マッチしました"

正規表現クイズ 第8問

5桁の数値と文字の組み合わせです。今回のケースだとマッチするでしょうか?

str = "000A"
if str =~ /0{3,4}/
  p "マッチしました"
else
  p "マッチしませんでした"
end

解答

"マッチしました"

正規表現クイズ 第9問

アルファベットの組み合わせ、今回のケースだとマッチするでしょうか?

str = "Ruby on Rails"
if str =~ /[A-Z][a-zA-Z]*/
  p "マッチしました"
else
  p "マッチしませんでした"
end

解答

"マッチしました"

正規表現クイズ 第10問

数値とアルファベットの組み合わせ、今回のケースだとマッチするでしょうか?

str = "12345Ruby"
if str =~ /[A-Z][a-zA-Z]/
  p "マッチしました"
else
  p "マッチしませんでした"
end

解答

"マッチしました"

正規表現クイズ 第11問

1文字のアルファベットに対して、今回のケースだとマッチするでしょうか?

str = "R"
if str =~ /[A-Z].+/
  p "マッチしました"
else
  p "マッチしませんでした"
end

解答

"マッチしませんでした"

正規表現クイズ 第12問

これが最後の問題です。

str = "080-4343-7650"
if str =~ /[0-9]{2,5}(-?)[0-9]{1,4}(-?)[0-9]{4}/
  p "マッチしました"
else
  p "マッチしませんでした"
end

解答

"マッチしました"

最後の問題は電話番号の確認を行う正規表現になります。

まとめ

いかがだったでしょうか。今回はRubyでの正規表現の使い方と、正規表現の基本的な文法について触れてみました。 Rubyで正規表現を使用する際は、if文でのパターンマッチによる条件分岐と、文字列の置換がほとんどだと思います。そういったケースでは正規表現をどんどん利用してみましょう!

余談ですがRubyはOnigumoとう強力な正規表現エンジンを採用しています。かっこいい名前ですね。

少し分かりづらいですが、こちらがOnigmoの文法になります。

image

Tech 2 GO編集部
ライター
Tech 2 GO編集部

関連記事