Help us understand the problem. What is going on with this article?

正規表現:正規表現修飾子編

More than 3 years have passed since last update.

正規表現:基礎編にて正規表現の基礎になる部分を書いたので今回は正規表現修飾子について書いてみようと思います。

使用しているrubyのバージョンは2.2.3です。

正規表現修飾子

正規表現修飾子は正規表現パターンの後ろに付与して使用することができます。

例:/パターン/x

修飾子 意味
i 大文字と小文字を無視する
m 複数行の文字列に対してマッチを試みる。改行は通常の文字として扱われ、.は改行にマッチする。
x 正規表現内に空白とコメントを挿入して見やすくできる。
o 正規表現リテラルが初めて評価されるときに限り、1度だけ#{}内の式展開を実行する。
u, e, s, n それぞれ、正規表現をUnicode(UTF-8), EUC, SJIS, ASCII(none)として解釈する。これらの修飾子が指定されていない場合、正規表現はソースエンコーディングを使っているものとみなされる。

1つずつ具体例を挙げつつ見ていきます。

i

大文字小文字の区別が無視されていることがわかります。

puts /Ruby/ =~ "Ruby" # => 0
puts /Ruby/ =~ "ruby" # => nil
puts /Ruby/ =~ "RUBY" # => nil

puts /Ruby/i =~ "Ruby" # => 0
puts /Ruby/i =~ "ruby" # => 0
puts /Ruby/i =~ "RUBY" # => 0

m

デフォルトだと「.」は改行を除く任意の1文字にマッチしますが、mの正規表現修飾子をつけた状態だと改行にもマッチします。

puts /Ruby.+と.+Python.+/ =~ "Ruby\n\nPython!" # => nil
puts /Ruby.+と.+Python.+/m =~ "Ruby\n\nPython!" # => 0

x

puts /Ruby#コメント/x =~ "Ruby" # => 0
puts /R u b y/x =~ "Ruby" # => 0
puts /Ru
by/x =~ "Ruby" # => 0

見やすいように適宜改行を入れて正規表現を記述する、という場合に便利です。
以下の欄やSublime Text上で色の付き方がおかしくなりますが、ちゃんと改行なしパターンと同様の動作結果になります。

puts /(ruby|Ruby|RUBY) # 大文字小文字どちらでも
と
(python|Python|PYTHON) # 大文字小文字どちらでも
/x =~ "Rubyとpython"
# => 0

ではx修飾子をつけた状態で空白を無視して欲しくない時はどうすればいいでしょうか。
その場合は「\」を使ってエスケープしてください。
また、コメントアウトの「#」についても「#」という文字として認識させたい場合は「\」でエスケープしてください。

puts /(We|You)\ are\ (engineers|students)/x =~ "We are engineers" # => 0

余談ですがこれはいけるのですが

puts /(We|You)\ are\ (engineers|students)  /x =~ "We are engineers" # => 0

これらはダメでした。

puts /  (We|You)\ are\ (engineers|students)  /x =~ "We are engineers"
# => 1回目の「\ 」で syntax error, unexpected $undefined, expecting end-of-input

puts /  (We|You)are(engineers|students)  /x =~ "Weareengineears"
# => 2回目の「(」でsyntax error, unexpected tIDENTIFIER, expecting end-of-input

最初の「\」の直後に空白や改行を入れるとうまくいかないみたい?

o

正直あまり使いどころがわかっていないですが、正規表現の評価がされた時1度だけ式展開がされ、以降は同じ正規表現オブジェクトを返す、というものです。

# oオプションをつけなかった場合
array = ["Ruby", "Python", "Java"]
array.each do |lang|
    if /#{lang}/ =~ lang
        puts lang
    end
end
# => Ruby
# => Python
# => Java

# oオプションをつけた場合
array = ["Ruby", "Python", "Java"]
array.each do |lang|
    if /#{lang}/o =~ lang
        puts lang
    end
end
# => Ruby

通常であれば毎回式展開が行われるので上の例ではRuby, Python, Java全てがif文でtrueになり出力されますが、oオプションを使うと同じ正規表現オブジェクトが返されるので、/Ruby/という正規表現で固定になり、Python, Javaは出力されないようです。
速度改善という意味では使えるのかも。

複数指定

正規表現修飾子は1個だけでなく複数指定することも可能です。
記述の順番は何でも構いません。

puts /楽しい ruby/ix =~ "楽しいRuby" # => 0
akatsuki174
iOS→Androidエンジニアになりました。それなりに使える言語はSwift, Objective-C, Kotlin, Java。 UX, データ分析, グロースハック, デザイン, 自然言語処理にも興味あり。 1分野に固まらず、いろんな分野のことについて書いていこうと思います。
techtrain
プロのエンジニアを目指すU30(30歳以下)の方に現役エンジニアにメンタリングもらえるコミュニティです。
https://techbowl.co.jp/techtrain/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away