Rubyプログラマー初心者にとって、正規表現の使い方がいまいちよくわからないと感じている人も多いのではないでしょうか?
正規表現の使い方をすぐに忘れてしまう
そんな正規表現をわかりやすく理解できるように本記事では解説を進めていきます。この記事では、
- 【基礎】そもそも正規表現とは?
- 【基礎】正規表現のパターン一覧
- 【実践】正規表現で文字列などの抽出を行うには?
- 【実践】正規表現で置換処理を行うには?
など、より実践的で具体的な内容まで幅広く解説をしていきます。ぜひ、この機会に正規表現をマスターし、使いこなせるようになりましょう。
そもそも正規表現とは?
正規表現とは、わかりやすく定義すると、ある一定の規則で並んでいる文字列を検出するための技術のことです。正規表現ってそもそもなんだろう、何をするためのもの?という方はまずは以下の記事を参考にしてください。
それでは、サンプルコードを用いて、具体的な使い方を学習していきましょう。
正規表現で文字列などの抽出を行うには?
ここでは、正規表現で文字列の抽出を行う、
- match
- pre_match
- post_match
- slice, slice!
について紹介していきます。
match(マッチした部分を取得する)
matchメソッドは正規表現にマッチした部分文字列を取得するときに使用します。
オブジェクト名 .match(/正規表現/)
以下の例では、正規表現で「*の勉強」にマッチする文字列を取り出しています。
string = "Rubyの勉強, Railsの学習" md = string.match(/.*の勉強/) p md[0] => "Rubyの勉強" string = "Rubyの勉強, Railsの勉強" md = string.match(/.*の勉強/) p md[0] => "Rubyの勉強, Railsの勉強"
プログラムで使用されている「*」は、検索文字列を含む文字列を取得するときに使用します。matchメソッドの詳しい使い方については、以下の記事でも解説しています。
pre_match(マッチした部分の前を取り出す)
pre_matchは正規表現にマッチした前の部分の文字列を取得します。
reg = /の勉強/.match("Railsの勉強をしよう") p reg.pre_match => "Rails"
post_match(マッチした部分の後を取り出す)
post_matchは正規表現にマッチした部分の後の文字列を取得します。
reg = /の勉強/.match("Railsの勉強をしよう") p reg.post_match => "をしよう"
slice, slice!(マッチした文字列を取り出す)
sliceはマッチした部分の文字列を取り出します。以下の例ではaから始まる最初の文字を取り出しています。
p "xxxabcxxxx".slice(/a../) => "abc" マッチしない場合はnilを返す p "xxxxxxx".slice(/a../) => nil slice!はレシーバからマッチした部分を削除します。 a = "xxxxaaaxxx" a.slice!(/a../) => "aaa" p a => "xxxxxx"
使用例
=~(マッチした部分のインデックスを返す)
=~を使用するとマッチした部分の最初のインデックスを取得します。
p /aaa/ =~ "aaabbb" => 0 p /aaa/ =~ "rubyaaa" => 4 マッチしない場合はnilを返す p /aaa/ =~ "ruby" => nil
!~ (マッチしなかったらtrueを返す)
!~を使用すると正規表現でマッチしなかたらtrueを返します。
p /aaa/ !~ "aaabbb" => false p /aaa/ !~ "rubyaaa" => false マッチしない場合はtrueを返す p /aaa/ !~ "ruby" => true
scan(マッチした部分をすべて配列で返す)
scanは正規表現でマッチした部分を取得して配列で返します。
「〇〇by」という文字列にマッチしたものを全て返す string = "of the ruby, by the ruby, for the ruby" p string.scan(/..by/) => ["ruby", ", by", "ruby", "ruby"]
正規表現で置換処理を行うには?
置換処理とは、ある対象を別の対象に置き換える処理となります。そのある対象を一致した全ての箇所に対して置換するか、最初に一致した箇所のみ置換するか、その処理したい内容に応じたメソッドがRubyには用意されています。
gsub, gsub!(一致した部分を全て置き換える)
ある対象を一致した全ての箇所に対して置換したい場合は、gsub、gsub!メソッドを利用します。基本的な使い方は以下となります。
置換対象.gsub(/置換したい文字/,置き換える文字)
gsubとgsub!の違いは、置換対象に対して置換後の内容に上書きするかしないかの違いとなります。具体的な使い方と2つのメソッドの違いを以下のサンプルコードで確認してみましょう。
#gsub target = "hello, hello, hello Ruby" puts target.gsub(/hello/, "morning") puts target #gsub! target2 = "hello, hello, hello Rails" puts target2.gsub!(/hello/, "morning") puts target2
実行結果
# gsub morning, morning, morning Ruby hello, hello, hello Ruby # gsub! morning, morning, morning Rails morning, morning, morning Rails
gsubメソッドもgsub!メソッドも置換した結果は同じですが、元の対象(target,target2)のデータも置換後の内容で上書きされるかされないかの違いがあることが確認できるかと思います。
sub, sub!(一致した最初の部分を置き換える)
次に一致した最初の部分だけを置き換えるメソッドです。それが、sub,sub!となります。
上記2つのメソッドの違いは、さきほどgsubの項目でご説明した内容と同じく、元のデータを上書きするかしないかの違いです。こちらも具体的なサンプルで確認してみましょう。
#sub target = "hello, hello, hello Ruby" puts target.sub(/hello/, "morning") puts target #sub! target2 = "hello, hello, hello Rails" puts target2.sub!(/hello/, "morning") puts target2
実行結果
#sub morning, hello, hello Ruby hello, hello, hello Ruby #sub! morning, hello, hello Rails morning, hello, hello Rails
上のサンプルで確認頂いた様に、最初に一致した箇所の文字だけ置換されていることが分かります。
正規表現で文字列などを分割するには?
文字列の分割にはsplit, split!メソッドを利用します。上記のメソッドを使うことで得られる結果(戻り値)は配列となります。こちらもサンプルコードを確認してみましょう。
string = "Hello, Ruby, World" p string.split(/s*,s*/) # 「,」で分割
実行結果
["Hello", "Ruby", "World"]
配列について、この機会に理解を深めておきたい方は以下の記事を参考にしてください。
メタ文字列の使い方
メタ文字列の一覧
メタ文字とは本来もつ文字の意味とは別に、プログラミングを行う上で定義した特別な意味を持つ文字列のことをメタ文字と呼びます。
特に正規表現の処理では、このメタ文字列がとても強力な武器となります。まずは、以下のメタ文字列の一覧をご確認下さい。
メタ文字 | 説明 | 使用例 | 合致する文字列 | 合致しない文字列 |
---|---|---|---|---|
. | 任意の1文字 | h.t | hat,hot,hit | head,height |
* | 直前のパターンを0回以上繰り返す | 山川* | 山,山川,山川川 | 里 |
+ | 直前のパターンを1回以上繰り返す | gre*n | greeeeeeen | grn |
? | 直前のパターンを0もしくは1回繰り返す | 山川? | 山,山川 | 山川川 |
{数字} | 直前のパターンを数字の分だけ繰り返し | 9{3} | 999 | 9,99,9999 |
[文字,文字] | カッコ内の文字のいずれか1文字 | [a,b,c] | a,b,c | d,e |
次に利用頻度の高いメタ文字の使用例をご紹介します。
繰り返しの表現
0回以上の繰り返しでは”*”を使用します。
string = "bbb" p string.gsub(/a*b/, "morning ") => "morning morning morning" string = "abbbabbaaaaab" p string.gsub(/a*b/, "morning ") => "morning morning morning morning morning morning "
一致する文字列
b ab aab
0回以上ということはaがあってもなくてもいいのでbでも一致するわけです。
1回以上の繰り返しでは”+”を使用します。
string = "bbb" p string.gsub(/a+b/, "morning ") => "bbb" string = "abbbabbaaaaa" p string.gsub(/a+b/, "morning ") => "morning bbmorning baaaaa"
一致する文字列
ab aab aaab
1回以上なので、bだけでは一致しません。
繰り返し回数が0回か1回のときは”?”を使用します。
string = "bbb" p string.gsub(/a?b/, "morning ") => "morning morning morning " string = "aab" p string.gsub(/a?b/, "morning ") => "amorning "
一致する文字列
b ab
0,1回なので、aaabなどは一致しなくなります。
繰り返し回数がちょうどn回のときは{n}を使用します。
string = "bbb" p string.gsub(/b{3}/, "morning ") => "morning " string = "bb" p string.gsub(/b{3}/, "morning ") => "bb"
一致する文字列
bbb
このように、ちょうどbbbが3回のときしかマッチしません。
繰り返し回数がn回以上のときは{n,}を使用します。
string = "bbb" p string.gsub(/b{2,}/, "morning ") => "morning " string = "bb" p string.gsub(/b{2,}/, "morning ") => "morning "
一致する文字列
bb bbb bbbb bbbbb
以上なので、際限なくマッチします。
繰り返し回数がn回以下のときは{,n}を使用します。
string = "abbb" p string.gsub(/ab{,2}/, "morning ") => "morning b" string = "a" p string.gsub(/ab{,2}/, "morning ") => "morning "
一致する文字列
a ab abb
n回以下なので、bが消えてaだけのときもマッチします。
繰り返し回数がn回以上、m回以下のときは{n,m}を使用します。
string = "xxxxabxxx" p string.gsub(/ab{1,2}/, "morning") => "xxxxmorningxxx" string = "xxxxabbbxxxx" p string.gsub(/ab{1,2}/, "morning") => "xxxxmorningbxxxx""
一致する文字列
ab abb
1回か2回のどちらもマッチするときは最大値の2でマッチします。
文字クラスの省略記法
a-z、A-Z、0-9のうちのいずれか1文字に一致する場合はwを使います。
string = "9a" p string.gsub(/wa/, "morning") => "morning" string = "Za" p string.gsub(/wa/, "morning") => "morning"
一致する文字列
2a 0a ja ia Oa
要するに英数字はすべてマッチします。
反対にa-z、A-Z、0-9のうちのいずれの1文字にも一致しない場合はWを使います。
string = "暑a" p string.gsub(/Wa/, "morning") => "morning" string = "na" p string.gsub(/Wa/, "morning") => "morning"
一致する文字列
n f 感 米
このように、英数字以外はマッチします。
空白文字にf,n,r,tに一致する場合はsを使います。
string = "ra" p string.gsub(/sa/, "morning") => "morning" string = "na" p string.gsub(/sa/, "morning") => "morning"
一致する文字列
n f n r
反対に空白文字にf,n,r,tに一致しない場合はSを使います。
string = "Aa" p string.gsub(/Sa/, "morning") => "morning" string = "0a" p string.gsub(/Sa/, "morning") => "morning"
一致する文字列
A s 0 K
10進数の数字に一致する場合は”d”を使用します。
string = "Aa" p string.gsub(/da/, "morning") => "Aa" string = "0323-3238-3232" p string.gsub(/d{4}/, "morning") => "morning-morning-morning"
一致する文字列
3 4 0
10進数の数字以外に一致する場合は”D”を使用します。
string = "#a" p string.gsub(/Da/, "morning") => "morning" string = "9a" p string.gsub(/Da/, "morning") => "9a"
一致する文字列
j i #
要するに、数字以外はなんでもマッチします。
文字列の行頭、行末、先頭、末尾で指定する方法
メタ文字列では文字列の位置を考慮して一致するかどうか判定できます。行頭を指定したい場合は”^”を使用します。行頭は先頭とは違い、nで改行されたあとの先頭も含めるので1つとは限りません。
string = "bbbnbbb" p string.gsub(/^bbb/, "morning") => "morningn" + "morning" string = "bbbnbbbnbbb" p string.gsub(/^bbb/, "morning") => "morningn" + "morningn" + "morning"
一致する文字列
行頭のbbb
行末を指定したい場合は”$”をを使用します。
string = "aaabbbnbbbaaa" p string.gsub(/bbb$/, "morning") => "aaamorningn" + "bbbaaa" string = "aaabbbnaaabbbnbbbz" p string.gsub(/bbb$/, "morning") => "aaamorningn" + "aaamorningn" + "bbbz"
一致する文字列
行末ののbbb
先頭を指定したい場合は”A”を使用します。
string = "aaabbbnaaabbb" p string.gsub(/Aaaa/, "morning") => "morningbbbn" + "aaabbb" string = "bbbbbnbbbbbnbbbz" p string.gsub(/Abb/, "morning") => "morningbbbn" + "bbbbbn" + "bbbz"
一致する文字列
先頭のaaa
改行後のaaaは含まれないことに注意してください。
末尾を指定したい場合は”z”を使用します。
string = "aaabbbnaaabbb" p string.gsub(/bbbz/, "morning") => "aaabbbn" + "aaamorning" string = "bbbbbnbbbbbnbbb" p string.gsub(/bbbz/, "morning") => "bbbbbn" + "bbbbbn" + "morning"
一致する文字列
末尾のbbb
正規表現早見表
正規表現は普段から使い慣れていないと、使い方を忘れてしまいがちです。以下の記事ではRubyで使用できる正規表現の文法をまとめていますので、ぜひ参考にしてください!
まとめ
この記事では、正規表現の使い方をついて、
- そもそも正規表現とは?
- 正規表現のパターン一覧
- 正規表現で文字列などの抽出を行うには?
- 正規表現で置換処理を行うには?
などについて解説しました。説明した便利なメソットを使いこなせば、的確に文字列を操作することができます。また、メタ文字列と組み合わせて使えば思い通りに文字列をマッチさせられるでしょう。
正規表現を覚えるには自分でさまざまなパターンを作成するのが一番の近道なので、独自の表現をたくさん作成してみてください。もし正規表現の使い方について忘れてしまったらこの記事を確認してくださいね!