🍒 はじめに
チェリー本輪読会の第9週目のエントリーになります。
輪読会の概要については第1週目にまとめています。
- 第1週目のエントリーはこちら
- 第2週目のエントリーはこちら
- 第3週目のエントリーはこちら
- 第4週目のエントリーはこちら
- 第5週目のエントリーはこちら
- 第6週目のエントリーはこちら
- 第7週目のエントリーはこちら
- 第8週目のエントリーはこちら
🍒 輪読会 第9週目まとめ
第6章6.3〜第6章6.4まで
期間:2021年07月19日〜2021年07月23日
第8週目で紹介したQiita記事の続きから進めました。
今週は、週の最後で第7章(クラス)にも入りましたが、こちらは第10週目の記事で取り上げたいと思います。
正規表現はRegexpクラスのオブジェクト
Rubyでは扱える全ての値はオブジェクトです。
class Regexp (Ruby 3.0.0 リファレンスマニュアル)
正規表現は、/
スラッシュで囲んだ形式で記述します。
\w
は、[a-zA-Z0-9_]
(半角英数字とアンダースコア1文字) と、同等の意味になります。
wは小文字です。大文字のWになると、意味が変わってきますので注意です。[^a-zA-Z_0-9]
(半角英数字とアンダースコア以外の1文字)になります。
regexp = /\w{6}-\d{3}/ => /\w{6}-\d{3}/ regexp.class => Regexp
=~ を使って正規表現を比較する
=~
を使い、マッチした場合はマッチした最初の文字列の位置が返り値として戻ってきます。
'MONGOL-800' =~ /\w{6}-\d{3}/ => 0
マッチしなかった場合は、nil
が返ってきます。
'GO!GO!-7188' =~ /\w{6}-\d{3}/ => nil
マッチした場合は真、マッチしなかった場合はnil(偽)を返す性質を利用し、if文などの条件分岐でよく使われます。
if 'MONGOL-800' =~ /\w{6}-\d{3}/ puts 'マッチしたさ〜' else puts 'マッチしないさ〜' end マッチしたさ〜
!~ を使って正規表現を比較する
!~
は、=~
の逆の結果が返ります。マッチしなかったときに真を、マッチしたときに偽を返せます。
if 'MONGOL-800' !~ /\w{6}-\d{3}/ puts 'マッチしたさ〜' else puts 'マッチしないさ〜' end マッチしないさ〜
キャプチャ機能
英語のcaptureは「捕まえる」「取る」の意味になります。そこから、コンピュータにデータを取り込むことを指す用語として使われています。正規表現のキャプチャ機能は、マッチした部分の一部を取り出すものです。()
を使い、抜き出したい部分を指定します。
キャプチャ機能でマッチした部分は、$数字
の形式で取り出すことができます。
/(\w{6})(-)(\d{3})/ =~ 'MONGOL-800' => 0 $1 => "MONGOL" $2 => "-" $3 => "800"
MatchDataオブジェクト
class MatchData (Ruby 3.0.0 リファレンスマニュアル)
matchメソッドを使い、MatchDataオブジェクトとして扱うことで、マッチした箇所を指定して取り出すこともできます。0は、マッチ全体を返します。
name = 'MONGOL-800' m = /(\w{6})(-)(\d{3})/.match(name) => #<MatchData "MONGOL-800" 1:"MONGOL" 2:"-" 3:"800"> m[1] => "MONGOL" m[2] => "-" m[3] => "800" m[4] => nil m[0] => "MONGOL-800"
キャプチャの結果に名前を付ける
上記の方法でキャプチャした結果に名前を付けることができます。(?<foo>)
というメタ文字を使います。キャプチャの結果に名前を付けることで、取り出すときに指定した名前で呼び出せます。名前があることで、何の値を取得しているのかが分かりやすくなります。
name = 'MONGOL800のメンバーはkiyosaku、takashi、satoshiです' m = /(?<band_name>\w{9})のメンバーは(?<bass>\w+)、(?<guitar>\w+)、(?<drums>\w+)です/.match(name) => #<MatchData... m[:band_name] => "MONGOL800" m[:bass] => "kiyosaku" m[:guitar] => "takashi" m[:drums] => "satoshi"
正規表現と組み合わせると便利なメソッド
scanメソッド
String#scan (Ruby 3.0.0 リファレンスマニュアル)
matchメソッドと似ていますが、scanメソッドは引数で渡した正規表現にマッチする部分を「配列」に入れて返します。(matchメソッドは、マッチした場合には結果を MatchData オブジェクトで返します。マッチしなかった場合 nil を返します。)
以下は、マッチした数字\d
を配列で返しています。
'MONGOL800 GO!GO!7188 10-FEET'.scan(/\d+/) => ["800", "7188", "10"]
()
を使い、キャプチャした部分を配列の配列で返すこともできます。
'MONGOL800 GO!GO!7188 10-FEET'.scan(/(\d+)/) => [["800"], ["7188"], ["10"]]
[ ] メソッド
[]
は、スクエアブラケット、角カッコと読みます。
エイリアスメソッド(slice)
[]
メソッドを使うと、文字列から正規表現にマッチした部分を抜き出すことができます。
band_name = 'MONGOL800 GO!GO!7188 10-FEET' band_name[/\w{6}\d{3}/] => "MONGOL800"
複数ある場合は、最初にマッチした文字列が返ります。
band_name = 'MONGOL800 LONDON700' band_name[/\w{6}\d{3}/] => "MONGOL800"
slice! メソッド
マッチした部分が文字列から破壊的に取り除かれます。
band_name = 'MONGOL800 GO!GO!7188 10-FEET' => "MONGOL800 GO!GO!7188 10-FEET" band_name.slice!(/\w{6}\d{3}/) => "MONGOL800" band_name => " GO!GO!7188 10-FEET"
gsubメソッド、gsub!メソッド
String#gsub (Ruby 3.0.0 リファレンスマニュアル)
第1引数の正規表現にマッチした文字列を、第2引数の文字列へ置き換えるメソッドです。
band_name = 'MONGOL800' band_name.gsub(/\d{3}/, '八百') => "MONGOL八百"
置き換え後に、変数band_nameを確認すると元に戻っています。
band_name => "MONGOL800"
破壊的に変更するには、gsub!
メソッドを使います。
band_name = 'MONGOL800' band_name.gsub!(/\d{3}/, '八百') => "MONGOL八百" band_name => "MONGOL八百"
正規表現オブジェクトを作成する
Regexp.new
Regexp.compile (Ruby 3.0.0 リファレンスマニュアル)
Regexp.new
の引数へ正規表現の文字列を渡すと、正規表現オブジェクトが作成できます。
正規表現オブジェクトを変数に代入して使いたいときは、以下のようにRegexp.newが必要です。
regexp = Regexp.new('\d+') => /\d+/ 'MONGOL800 GO!GO!7188 10-FEET'.scan(regexp) => ["800", "7188", "10"]
%r (%記法)
//
の代わりに%r
記法を使うこともできます。
以下、4つとも同じ意味です。
/foo/ => /foo/ %r{foo} => /foo/ %r!foo! => /foo/ %r?foo? => /foo/
//
を使う場合は、スラッシュをエスケープする必要があります。
/http:\/\/www\.google\.com/ => /http:\/\/www\.google\.com/
%r
を使うときは、スラッシュのエスケープ処理は不要です。ただし、.
についてはメタ文字のため、エスケープ処理が必要になります。
%r{http://www\.google\.com} => /http:\/\/www\.google\.com/
case文で正規表現を使う
case文は、whenで指定した値に一致するかどうかを===
演算子を使って判定しています。==
ではありません。(===
演算子 についての詳細は、チェリー本269頁)
===
演算子を使うことで、オブジェクトのデータ型を識別することができます。
配列の場合
array = [1,2,3] case array when String puts '文字列' when Array puts '配列' when Regexp puts '正規表現' end 配列
正規表現の場合
regexp = Regexp.new('\d+') case regexp when String puts '文字列' when Array puts '配列' when Regexp puts '正規表現' end 正規表現
when節に正規表現を指定して、以下のようにマッチする文字列を判定するときに使うこともできます。
band_name = 'MONGOL800' case band_name when /\w{6}\d{3}/ puts 'モンパチ' when /\d{3}/ puts '八百' end モンパチ
輪読会メンバーがLT会へ登壇!
今回のブログを書き始めた8月7日のこの日、フィヨルドブートキャンプ内で開催されるLT会へ参加しました。輪読会メンバーのぺろさん(id:mosshu0703)と、いっしーさん(id:isshi-hasegawa)が登壇されたのですが、とても良かったので当ブログでも感想を書きたいと思います。
隣の芝生はいつも青い
フィヨルドブートキャンプは、メンターさん、アドバイザーさんをはじめ、同じ受講生でも凄い方が多く、隣どころか360度青くしか見えない私にとって、ぺろさんの発表はとても勇気がもらえました。
自分の庭に集中しよう
ほんとコレですね。
分からないことやできないこと、詰まって思い悩むことは今でも頻繁にありますが、そんなときこそ、ぺろさんのLTを思い出し、目の前のことに集中し人と比べず取り組んでいきたいと思います。
エモくて元気になれる素敵なLTでした!サンクス!
eminoprogramming.hatenablog.com
2021年フィヨルドブートキャンプの旅
映画が好きないっしーさん。物語のような発表構成で、スライドの冒頭からその世界観に引き込まれました。普段から輪読会やもくもく会などで積極的にコミュニケーションを取られている姿や、何でも器用にこなしている姿しか知らなかったので、今までの独学期間で思い悩まれていた話しなどは意外でした。当時の苦労があったからこその今に繋がっているんですね。それにしてもまだ3ヶ月ってのは本当に凄い!
技術や言語が好きになる = マジ最強💪
もちろん、ほとんどの受講生が転職やスキルアップなど、何らかしらの現実的な目標を持ち学習に取り組んでいるとは思いますが、シンプルに「好き」だからやる。これが一番最強なんだと思えました。あれやこれやと考え、上手くいかないことも多かったりするのですが、もっとシンプルに考えていきたと思いました。私もまだまだ旅の途中ですが、楽しんで経験値を積み、まずはフィヨルドブートキャンプというゲームのクリアを目指し、頑張っていきたいと思います!
「好き」に繋がりますが、我らが輪読会のオーガナイザー、トミーさん(id:eatplaynap329)のアツいツイートもご紹介🔥
学習コストなんて知るか人生はやりたいことをやる場所
— トミー (@eatplaynap329) August 6, 2021
参考書籍
- 伊藤淳一 著/『プロを目指す人のためのRuby入門 言語仕様からテスト駆動開発・デバッグ技法まで』/技術評論社/2017年https://gihyo.jp/book/2017/978-4-7741-9397-7
- 高橋征義、後藤裕蔵 著/『たのしいRuby第6版』/SBクリエイティブ/2019年https://tanoshiiruby.github.io/6/index.html
- プログラミング言語 Ruby リファレンスマニュアル https://docs.ruby-lang.org/ja/
- 小餅良介 著/ 『独習Ruby on Rails』https://www.shoeisha.co.jp/book/detail/9784798160689
🍒 まとめ
正規表現の章を終え、基礎を学んだことで、「意味不明の恐ろしい呪文」がそうではなくなりました。他の場所で見かける正規表現に対しても、「ひとつひとつ調べればわかる」と、うろたえることなく扱えるようになったことは、またひとつ自信になりました。
いよいよ次は、最初の関門「クラス」の章に入ります。
オブジェクト指向の知識も必要となってくる章となり、難易度がグッと上がります。
では、また来週!(次回、第10週目)