プログラミングで複雑なルールによる入力チェックや、文字列置換を行いたい時に正規表現を使えると非常に便利です。
複雑な入力チェックの処理をいくつも記述すると分かりづらいコードで、不具合の原因となる場合もあります。
正規表現を用いるとシンプルな記述方法で、簡潔なロジックで表すことができます。
その一方で、正規表現自体の記述方法はルールがたくさんあり、すべてを覚えるのは困難です。
必要な時に調べれば良いので、すべてを覚える必要はないと思いますが、どんなことができるのかは知っておく必要があります。
そこで本記事では、Rubyの正規表現についての記述方法やできることについてまとめます。
プログラミング初心者の方の学習や、忘れてしまった方の復習として、参考にしていただければ幸いです。
記載しているプログラムは、Ruby2.7.1を使って動作確認をしています。
Rubyの正規表現
Rubyの正規表現として以下の内容を採り上げます。
- 正規表現の作成方法
- 正規表現による文字列チェック
- 正規表現による文字列置換
- 正規表現による文字列抽出
- 正規表現のエスケープ
正規表現の作成方法
Rubyで正規表現を扱うには、3種類の作成方法があります。
- /正規表現/ で作成する
- %r{正規表現} で作成する
- Regexp.new で正規表現オブジェクトを作成する
いずれも標準機能として提供されていて、機能として大きな違いはありません。
本記事では、/正規表現/ で正規表現を表しています。
正規表現にはたくさんの特殊文字やオプションがありますが、詳細はリファレンスマニュアルをご参照ください。
正規表現による文字列チェック
正規表現による文字列チェックは、Regexpクラスのメソッドを使う方法とStringクラスのメソッドを使う方法があります。
引数などが異なりますが、どちらも結果は同じです。
match?メソッド
match?メソッドは、指定した文字列が正規表現にマッチするはtrueを返し、マッチしない場合はfalseを返します。
str = "Hello Ruby!!" regex = /Ruby/ puts regex.match?(str) # -> true puts str.match?(regex) # -> true
正規表現にはオプションを付けることができます。
よく使われるのは、大文字小文字を区別せずにマッチさせるオプションの i です。
str = "Hello Ruby!!" regex = /ruby/i puts regex.match?(str) # -> true puts str.match?(regex) # -> true
matchメソッド
matchメソッドは、正規表現に最初にマッチした文字列(MatchDataオブジェクト)を返します。
マッチしない場合はnilを返します。
str = "Hello Ruby!!" regex = /Ruby/ puts regex.match(str) # -> Ruby puts str.match(regex) # -> Ruby
=~メソッド
Regexpクラスの=~メソッドは、正規表現に最初にマッチした文字列の位置のインデックスを返します。
先頭から一致する場合は0を返します。
マッチしない場合はnilを返します。
str = "Hello Ruby!!" regex = /Ruby/ puts regex =~ str # -> 6
正規表現による文字列置換
正規表現による文字列置換は、Stringクラスのgsub、subを使います。
gsubメソッド
gsubメソッドは、正規表現にマッチする文字列をすべて置換します。
str = "Hello Ruby!!" regex = /\w/ rep = "*" puts str.gsub(regex, rep) # -> ***** ****!!
上記のプログラムでは英字をアスタリスクに置換しています。
subメソッド
subメソッドは、正規表現にマッチする文字列の最初のみを置換します。
str = "Hello Ruby!!" regex = /\w/ rep = "*" puts str.sub(regex, rep) # -> *ello Ruby!!
正規表現による文字列抽出
正規表現で指定した部分を文字列から抽出するには、抽出したいパターンに括弧を含めて指定します。
gsubメソッドで抽出した文字列を使って置換をする場合は、抽出した文字列を$1、$2を使って取得します。
str = "Hello Ruby!!" regex = /(\w+)\s(\w+)/ puts str.gsub(regex, "#{$2} #{$1}") # -> Ruby Hello!!
matchメソッドで一致した文字列を抽出する場合は、戻り値のMatchDataオブジェクトのcapturesで取得する方法があります。
抽出した文字列が配列で返されます。
str = "Hello Ruby!!" regex = /(\w+)\s(\w+)/ puts regex.match(str).captures.inspect # -> ["Hello", "Ruby"]
置換の時と同様に、$1、$2を使っても取得できます。
str = "Hello Ruby!!" regex = /(\w+)\s(\w+)/ regex.match(str) puts "#{$1} #{$2}" # -> Hello Ruby
また、抽出した文字列を名前付き変数として扱うことも出来ます。
str = "Hello Ruby!!" regex = /(?<a>\w+)\s(?<b>\w+)/ puts str.gsub(regex, '\k<b> \k<a>') # -> Ruby Hello!!
上記のプログラムでは、1つ目に抽出した結果をa、2つ目に抽出した結果をbに格納し、置換後の文字列に指定しています。
?<変数名>で抽出し、k<変数名>で参照します。
正規表現のエスケープ
正規表現においてピリオドやプラス、アスタリスクなどの記号は、特殊文字として定義されている文字です。
これらを文字列に含んでいる場合の正規表現を作成する場合は、特殊文字として扱われないようにエスケープする必要があります。
エスケープは、特殊文字の直前にバックスラッシュを付けます。
str = "Hello+Ruby." regex = /\w+\+\w+\./ puts regex.match?(str) # -> true
上記のプログラムでは、プラスとピリオドの直前にバックスラッシュを入れてエスケープした正規表現を作成しています。
また、エスケープが必要な文字が含まれている文字列全体をプログラムによってエスケープしたい場合は、Regexpクラスのescapeメソッドでエスケープ処理が行なえます。
str = "Hello+Ruby." puts Regexp.escape(str) # -> Hello\+Ruby\. puts str.match?(Regexp.escape(str)) # -> true
正規表現はプログラム外でも役に立つ
正規表現はプログラムをシンプルにしてくれる便利なものですが、プログラム外でも役に立つことがあります。
エディタを使って文章を書いている際に、文字列の検索や置換をしたくなった場合に、正規表現で指定することが可能なエディタもあります。
Linuxのコマンドでも正規表現を使えるコマンドがたくさんあります。
Excelの関数などでも正規表現を使うことができます。
正規表現で書いてみたけど、思うようにマッチしないという場合には、正規表現チェッカーというツールで分かりやすく一致部分を表現してくれるツールもありますので活用してみてください。
正規表現は記述方法が難しいのですが、書けると非常に効率を上げてくれる手段になります。
サラッと正規表現を書ける人はカッコいいですよね。
今回はRubyの正規表現についてまとめました。
以上、参考になれば幸いです。
コメント