Ruby正規表現応用術
正規表現の基礎
Rubyで正規表現を扱う際の基本構文は、Regexpクラスを利用します。最も簡単な形はリテラル表記で、/abc/のようにスラッシュで囲む方法です。これを使って文字列に対してmatchメソッドを呼び出すと、マッチした部分がMatchDataオブジェクトとして返ります。例えば"abc".match(/abc/)はMatchDataを返し、nilが返るとマッチしません。
複数回のマッチを取得したい場合はscanメソッドを使用します。"abcabc".scan(/abc/)は["abc", "abc"]という配列を返します。文字列を区切り文字で分割したいときはsplitメソッドが便利です。"a,b,c".split(/,/)は["a", "b", "c"]を生成します。
さらに、~演算子を使うと、文字列が正規表現にマッチしたかどうかを簡潔に判定できます。"abc" =~ /abc/は0(マッチ位置)を返し、マッチしない場合はnilになります。これにより条件分岐での使用がスムーズです。
regex = /abc/
"abc".match(regex) # => #<MatchData "abc">
"abcabc".scan(regex) # => ["abc", "abc"]
"a,b,c".split(/,/) # => ["a", "b", "c"]
"abc" =~ /abc/ # => 0
高度な置換とキャプチャ
正規表現の強力な機能の一つにキャプチャグループがあります。(...)で囲んだ部分は後で参照でき、$1、$2などでアクセスします。例えば"John Doe".match(/(\w+)\s+(\w+)/)は$1 = "John"、$2 = "Doe"となります。
置換時にキャプチャを利用することで、文字列の並び替えやフォーマット変更が簡単に行えます。"foo bar".gsub(/(\w+)\s+(\w+)/, '\2 \1')は"bar foo"を返します。さらに、ブロックを渡すことで動的に置換値を計算できます。"foo123bar".gsub(/(\d+)/) { |m| m.to_i * 2 }は"foo246bar"になります。
"John Doe".match(/(\w+)\s+(\w+)/)
# $1 => "John", $2 => "Doe"
"foo bar".gsub(/(\w+)\s+(\w+)/, '\2 \1')
# => "bar foo"
"foo123bar".gsub(/(\d+)/) { |m| m.to_i * 2 }
# => "foo246bar"
このようにRegexpとmatch、scan、split、~演算子を組み合わせることで、テキスト処理の幅が大きく広がります。正規表現リテラルを活用し、キャプチャと高度な置換を駆使して、実務で頻繁に直面する文字列操作を効率化しましょう。
実践例とTips
Ruby実践で正規表現を使う代表的なケースとして、ログ解析やメールアドレス検証があります。ログファイルの行から日付を抽出する例を示します。
log_lines.each do |line|
if line =~ /\[(\d{4})-(\d{2})-(\d{2})\]/
year, month, day = $1, $2, $3
# ここで日付を使った処理
end
end
メールアドレスのバリデーションも正規表現で簡潔に実装できます。/\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/iというリテラルを使えば、RFC 5322に準拠した簡易チェックが可能です。
さらに、複数行にわたるテキストから特定パターンを抜き出す際は、Regexp::MULTILINEフラグを付与してscanを使うと便利です。例えば、複数行にわたるコメントブロックを抽出する場合、/\/\*.*?\*\//mのように書きます。
最後に、正規表現を使う際のベストプラクティスとして、以下を意識しましょう。
- リテラル表記は可読性が高いので、可能な限り使用する。
- キャプチャグループは必要最低限に抑え、過剰なグループ化は避ける。
- パフォーマンスが重要な場合は、
Regexp::IGNORECASEやRegexp::EXTENDEDを適切に組み合わせる。 - テストコードで正規表現の挙動を検証し、予期せぬマッチを防ぐ。
これらを踏まえてRuby実践で正規表現応用を行えば、コードの保守性と可読性を高めつつ、複雑な文字列処理をシンプルに実装できます。
コメント
コメントを投稿