【ruby】Rubularで正規表現練習 第四回
ついに本当のRegex最終回!
今回もRubularさんにお世話になります!
今回扱うのはOptionsです。
i :case insensitive (大文字と小文字の区別をなくす。Upper caseが大文字、Lower caseが小文字、insensitiveが鈍感という意味なので。)
m :make dot match newlines (ドットを改行にマッチさせる)
x :ignore whitespace in regex (Regex内の空白(スペース)を無視する)
o :perform #{...} substitutions only once (置換(式展開)を一度のみ実行する)
Optionsは下記赤枠の部分に入れて使います。(実際は /[abc]/i のように使う)
使い方を見ていきましょう!!
1. i
大文字と小文字の区別をなくす。
Regex: /[a-z]/i
テストサンプル:
Apple Banana Cherry
つまり、小文字のアルファベット[a-z]なのに、大文字のアルファベットもマッチしています。
/[a-z]/i は、/[a-zA-z]/と一緒という意味ですね!短いコードで書ける!
オプション無しで試してみると、違いが分かると思います。
Regex: /[a-z]/
テストサンプル:
Apple Banana Cherry
2. m
ドットを改行にマッチさせる
前回、ドット(.)はすべての1文字というRegexでしたが、実は改行はドット(.)はマッチしない。
例えば、
Regex: /./
テストサンプル:
a
(改行)
(改行)
(スペース)
改行はマッチしていないことが分かります!
ここで、mオプションをつけてみると、、、
Regex: /./m
テストサンプル:
a
(改行)
(改行)
(スペース)
改行もドット(.)でマッチさせることができました!
3. x
Regex内の空白(スペース)を無視する。Regexの中にスペースを間違って入れちゃった場合、思った挙動と違う動きをしてしまうことがあります。
Regex: /(スペース)(スペース)a/
テストサンプル:
(スペース)(スペース)a
a
(スペース)a
丁寧に、スペースの数も一緒じゃないとマッチしていないのが分かります。
スペースは入っていても、無視してほしい!というときにxオプションを使ってみます。
Regex: /(スペース)(スペース)a/x
テストサンプル:
(スペース)(スペース)a
a
(スペース)a
全部のaがマッチしました!
スペースを含めてマッチさせたいときは、
xオプション無しで、\s(スペース一文字)を使って明示的に示すと、読みやすいかな!と個人的には思います!
こんな感じ
Regex: /\s\sa/
テストサンプル:
(スペース)(スペース)a
a
(スペース)a
※\sを使っても、xオプションを付けてしまうと、スペースは無視されてしまうので注意です。
4. o
置換(式展開)を一度のみ実行する
まず、式展開とは???というところから説明したいと思います。
rubyではダブルクォーテーション("")で囲まれた文字列内に変数を書いたり、Regex内に変数を書きたいとき、下記のように#{}を書いて、変数を展開します。
text = "式展開"
puts "ここで#{text}がされました"
if "式展開" =~ /^#{text}$/
puts "match!"
else
puts "not match!"
end
=>result
ここで式展開がされました
match!
* puts "ここで#{text}がされました"
文字列をprintします。#{text}で変数textが展開されます。なので、結果は"ここで式展開がされました。"となります
* if "式展開" =~ /^#{text}$/
rubyではif else endでif分を書きます。Regexは=~でつなげることで、matchしたかを判定します(match関数を使用する方法もあります)。Regex内でも#{text}で変数textが展開されます。
それでは、肝心のo オプションの説明にいきましょう!
これは、いつものRebularではテストができないので、下記サイト(Online上でRubyが実行できる)で検証していきます!(もちろんlocalのbashなどでrubyが実行できる方はそちらを使用していただいてOKです)
まず、oオプションがない場合、test_match(compare_text, sample)という、二つの引数が同じかどうかを比べる関数をループの中で使ってみます。
def test_match(compare_text, sample)
sample =~ /^#{compare_text}$/
end["test1","test1"].each do |test|
if test_match("test1",test)
puts "match!!"
else
puts "not match!!"
end
end["test2","test2"].each do |test|
if test_match("test2",test)
puts "match!!"
else
puts "not match!!"
end
end
上のループでは配列["test1","test1"]の内部を、ひとつずつ調べて、"test1"と一緒かをしらべています。
下のループでは配列["test2","test2"]の内部を、ひとつずつ調べて、"test2"と一緒かをしらべています。
すべて一緒なので、結果はmatch!!が四回表示されています。
それでは、次はoオプションをつけてみます。
def test_match(compare_text, sample)
sample =~ /^#{compare_text}$/o
end["test1","test1"].each do |test|
if test_match("test1",test)
puts "match!!"
else
puts "not match!!"
end
end["test2","test2"].each do |test|
if test_match("test2",test)
puts "match!!"
else
puts "not match!!"
end
end
下のループの結果がnot match!!になっています。なぜこんなことに????
実は、oオプションは、「Regexを使用する関数」を実行する際に、毎回Regexをコンパイルするのではなく、最初の一度のみコンパイルするようになります。そうすることで処理を軽くするために使用するようです。たとえば、1000回ループ内で、その関数を実行するなど。
ただ、上記の例のように、思わぬバグを招く可能性があるので、注意が必要です!!
本当の本当に、Regex練習おわったったーーー!!
まだまだRegexは難しい使い方があるとは思いますが、基本のキはこれでマスターできたかな?と思います!お付きあい、ありがとうございました!
これからも仲良くしていこうね、、、、Regexちゃん、、、、
今後も自信をもって「プロのエンジニア」を名のれるようになるべく、エンジニア必須科目についてブログで扱っていこうと思います。
おやすみなさいいいぃぃぃ