Roll With IT

tamakiのIT日記

チェリー本輪読会 第9週目まとめ

f:id:shirotamaki:20210619091936p:plain

🍒 はじめに

チェリー本輪読会の第9週目のエントリーになります。

輪読会の概要については第1週目にまとめています。

🍒 輪読会 第9週目まとめ

第6章6.3〜第6章6.4まで

期間:2021年07月19日〜2021年07月23日

第8週目で紹介したQiita記事の続きから進めました。

今週は、週の最後で第7章(クラス)にも入りましたが、こちらは第10週目の記事で取り上げたいと思います。

正規表現Regexpクラスのオブジェクト

Rubyでは扱える全ての値はオブジェクトです。

正規表現は、Regexpクラスになります。

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)

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ヶ月ってのは本当に凄い!

技術や言語が好きになる = マジ最強💪

もちろん、ほとんどの受講生が転職やスキルアップなど、何らかしらの現実的な目標を持ち学習に取り組んでいるとは思いますが、シンプルに「好き」だからやる。これが一番最強なんだと思えました。あれやこれやと考え、上手くいかないことも多かったりするのですが、もっとシンプルに考えていきたと思いました。私もまだまだ旅の途中ですが、楽しんで経験値を積み、まずはフィヨルドブートキャンプというゲームのクリアを目指し、頑張っていきたいと思います!

isshi-hasegawa.hatenablog.com

「好き」に繋がりますが、我らが輪読会のオーガナイザー、トミーさん(id:eatplaynap329)のアツいツイートもご紹介🔥

参考書籍

🍒 まとめ

正規表現の章を終え、基礎を学んだことで、「意味不明の恐ろしい呪文」がそうではなくなりました。他の場所で見かける正規表現に対しても、「ひとつひとつ調べればわかる」と、うろたえることなく扱えるようになったことは、またひとつ自信になりました。

いよいよ次は、最初の関門「クラス」の章に入ります。

オブジェクト指向の知識も必要となってくる章となり、難易度がグッと上がります。

では、また来週!(次回、第10週目)