SlideShare a Scribd company logo
1 of 19
Download to read offline
Ruby の
正規表現について
2019/05/15
大手町.rb #17
大手町.rb #17 「Ruby の正規表現について」
1自己紹介
Tomoya Kawanishi a.k.a. @cuzic
エネチェンジ株式会社 チーフエンジニア
電力会社、ガス会社を切り替えるなら、エネチェンジ経由で!
一般家庭も!法人も!
Ruby関西の中の人
2019年7月13日(土) 第87回Ruby関西勉強会
2019年9月15日(日) 大阪RubyKaigi 02
発表者として登壇くださる方、あとで声かけください。
大手町.rb の中の人
毎月 大手町.rb の開催を予定
東京駅、各線大手町駅から直結!
Ruby の初級者がメインターゲット
大手町.rb #17 「Ruby の正規表現について」
今日のテーマ
Ruby の正規表現について
正規表現という用語について
英語の Regular Expression の日本語訳
言語学では「正則表現」
expression は「表現」以外に「式」という意味もある
違和感があるが、いまさらどうしようもない
正規表現はなぜ重要か
正規表現を使うと
特定の文字列にマッチするかどうかの判定ができる
文字列の一部を取得(capture)することがカンタンにできる
ログ処理、テキストバリデーションなどがカンタンにできる
特徴
ほぼすべての言語で実装されており、応用範囲が幅広い
非常にコンパクトに記述でき、可読性、メンテナンス性が高い
知る人ぞ知る機能も多いがベンリ
2
大手町.rb #17 「Ruby の正規表現について」
正規表現の作り方
/hoge/ のように / で正規表現を作るのが一般的
中に / があるときは %r 記法を使う
正規表現にしたい文字列を引数で受け取るときなどは
Regexp.new を使うこともある
/ や %r の中では 式展開 #{} を使うこともできる
3
/hoge/ : もっとも一般的
%r(https://enechange¥.jp) # % 記法。
Regexp.new("https://enechange¥¥.jp") # Regexp.new
Regexp.compile("https://enechange¥¥.jp") # Regexp.compile
production_domain = "enechange¥¥.jp"
%r(https://#{production_domain})
大手町.rb #17 「Ruby の正規表現について」
正規表現の例
正規表現を使うと、文字列マッチが簡単にできる
^ : アンカーの一つ。行頭にマッチする
() : 正規表現の一部をキャプチャするときに使う
. : メタ文字の1つ。改行を除く任意の1文字にマッチ
+ : メタ文字の1つ。直前の部分式を1回以上の繰り返し
にマッチ
4
url = "https://enechange.jp/try/input"
# / を使った正規表現リテラル。 マッチした position を返す。
url =~ /^https:¥/¥/enechange¥.jp/(.+)/ #=> 0
$1 #=> "try/input"
# %r を使った正規表現リテラル
url =~ %r(^https://enechange¥.jp/(.+))
# String#match? を使うと true false を返す
url.match?(%r(¥Ahttps://enechange¥.jp/(.+)))
大手町.rb #17 「Ruby の正規表現について」
正規表現visualizer
Regulex という正規表現の visualizer がある。
慣れないうちは visualizer を使って、
その正規表現がどういう処理になるかを確認しながら、
進めると良い
5
# %r を使った正規表現リテラル
url =~ %r(^https://enechange¥.jp/(.+))
大手町.rb #17 「Ruby の正規表現について」
正規表現を学ぶときのコツ
正規表現は仕様が膨大
すべてを最初から理解して使いこなす必要はない
業務で必要になる都度、少しずつ理解している範囲を広
げるといい
正規表現の練習用サイトもある
https://regexone.com/
https://www.hackerrank.com/domains/regex
正規表現マッチを簡単に確認できるサイトもある
http://refiddle.com/
https://rubular.com/
いろいろ既存サービスを使いこなして、上達を目指しま
しょう
6
大手町.rb #17 「Ruby の正規表現について」
文字マッチ 7
. : 改行を除く任意の1文字
¥から始まらない文字 a など : a にマッチ
¥n : 改行にマッチ
¥記号 ¥/ ¥. など : その記号1文字にマッチ
¥w : 単語構成文字。 英小文字、英大文字、数字、アンダースコア、a-zA-Z0-9_
¥s : 空白文字。半角空白、タブ、改行、ほか [ ¥t¥r¥n¥f¥v]
¥d : 0から9 の数字
[abc] : 文字 a か b か c
[0-3] : 文字、 0 1 2 3 にマッチ
"2019-05-15".match?(/20¥d¥d-[01]¥d-[0-3]¥d/)
"example@example.jp".match?(/[-.¥w]+@)[-.¥w]+¥.jp/)
大手町.rb #17 「Ruby の正規表現について」
アンカー 8
^ : 行頭にマッチ
$ : 行末にマッチ
¥A : 文字列の先頭にマッチする
¥Z : 文字列の末尾にマッチ。ただし、改行が最後にあるときはその直前にマッチ。
¥z : 文字列の末尾にマッチする。
¥b : 単語の境界にマッチする
body = File.read("/etc/passwd")
body =~ /root/ #=> 0
body =~ /nobody/ #=> 818
body =~ /¥Aroot/ #=> 0
body =~ /¥Anobody/ #=> nil
body =~ /bash$/ #=> 27
body =~ /bash¥Z/ #=> 2248
body =~ /bash¥z/ #=> nil
アンカーとは
幅0 の文字列にマッチするメタ文字列
大手町.rb #17 「Ruby の正規表現について」
繰り返し、量指定子 9
* : 0回以上
+ : 1回以上
? : 0回もしくは1回
{n} :ちょうどn回(nは数字)
{n,} : n回以上(nは数字)
{,m} : m回以下(mは数字)
{n,m} : n回以上m回以下(n,mは数字)
直前の部分式を何回繰り返すかを指定する
欲張り(greedy)マッチ。最長の文字列にマッチする
"2019-05-15".match?(/¥d{4}-¥d¥d?-¥d¥d?/)
"2019-05-15".match?(/¥d{4}(-¥d{1,2}){2}/)
# /¥d{4}-¥d{1,2}-¥d{1,2}/ と同じ。
'<a href="#">'.match?(/¥<a¥s+href='?"?#'?"?¥s*¥>/)
m = '<div><a href="#">top</a></div>'.match(/<.+>/)
m[0] #=> "<div><a href=¥"#¥">top</a></div>"
m = /^.*(¥d+)¥./.match("Copyright 2013.")
m[1] #=> 3
大手町.rb #17 「Ruby の正規表現について」
最小量指定子
直前の部分式を何回繰り返すかを指定する
最短の文字列にマッチする
10
*? : 0回以上
+? : 1回以上
?? : 0回もしくは1回
{n}? :ちょうどn回(nは数字)
{n,}? : n回以上(nは数字)
{,m}? : m回以下(mは数字)
{n,m}? : n回以上m回以下(n,mは数字)
m = '<div><a href="#">top</a></div>'.match(/¥<.+?¥>/)
m[0] #=> "<div>"
m = /^.*?(¥d+)¥./.match("Copyright 2013.")
m[1] #=> 2013
大手町.rb #17 「Ruby の正規表現について」
キャプチャ
丸括弧()で、キャプチャできる
11
regex = %r(¥<a href="(.+?)".*?>(.+?)</a>)
m = '<div><a href="#">top</a></div>'.match(regex)
m[1] #=> "#"
m[2] #=> "top"
大手町.rb #17 「Ruby の正規表現について」
いずれかへのマッチ
縦棒(パイプ) | で、複数の正規表現のどれかにマッ
チするかどうかという判定ができる
凝った正規表現を書くよりは、
| で分割する方が分かりやすいこともある
12
request.fullpath.match?(%r(¥A/(login|logout)))
# "/login" や "/logout" 、 "/login?from=blahblah" などにマッチする
message =~ /([0-9a-zA-Z]|[0-9a-zA-Z])+/
大手町.rb #17 「Ruby の正規表現について」
正規表現関連のメソッド (String クラス) 13
# String#[regex] : 正規表現にマッチした文字列を返す
"We are hiring"[/¥b¥w+$/] #=> "hiring"
# String#[regex, index] : 正規表現にマッチし、その index のキャプチャ文字列を返す
"We are hiring"[/.+¥b(¥w+)$/, 1] #=> "hiring"
# String#=~ : 正規表現とマッチした position を返す
"We are hiring" =~ /¥b(¥w+)$/ #=> 7
# String#match : 正規表現とマッチした MatchData オブジェクトを返す
"We are hiring".match(/¥b(¥w+)$/) #=> #<MatchData "hiring" 1:"hiring">
body = File.read("/etc/passwd")
index = body =~ /bash$/
body.match(/^.+bash$/, index) # index 文字目からサーチを開始する
# String#match? : マッチ結果を true、 false で返す。動作が速い。
"We are hiring".match?(/¥b(¥w+)$/) #=> true
String クラスで正規表現関連で特に有用なメソッドを
5つ紹介します
大手町.rb #17 「Ruby の正規表現について」
正規表現関連のメソッド (Regexp クラス) 14
# Regexp.quote : 正規表現をエスケープする
prod_url = "https://enechange.jp"
/¥b#{prod_url}¥b/ =~ "https://enechangeejp" #=> 0 マッチする
/¥b#{Regexp.quote(prod_url)}¥b/ =~ "https://enechangeejp" #=> nil。マッチしない。
# Regexp.union( pat1, pat2, …) : 引数のいずれかにマッチする正規表現を返す
# 複雑な正規表現を段階的に構築したいときに便利
re_letter = Regexp.union(/[0-9a-zA-Z]/, /[0-9A-Za-z]/)
message =~ /#{re_letter}+/
# Regexp#match、 Regexp#match? : String クラスの対応するメソッドと同じ
Regexp クラスで正規表現関連で特に有用なメソッドを
3つ紹介します
大手町.rb #17 「Ruby の正規表現について」
正規表現関連のメソッド (MatchData クラス) 15
body = File.read("/etc/passwd")
m = body.match(/.+:(.+?sh)$/)
# MatchData#captures で括弧 () でキャプチャした文字列を配列で取得できる
m.captures #=> ["/bin/bash"]
# MatchData#[] でマッチした文字列を配列のようにアクセスできる
m[0] #=> "root:x:0:0:root:/root:/bin/bash"
m[1] = "/bin/bash"
m.pre_match #=> ""
m.post_match #=> "¥ndaemon:…(snip)"
# MatchData#begin(index) で index に対応する要素の開始位置が分かる
m.begin(0) #=> 0
m.begin(1) #=> 22
# MatchData#end(index) で index に対応する要素の終了位置が分かる
m.end(0) #=> 31
m.end(1) #=> 31
m2 = body.match(/.+:(.+?sh)$/, m.end(0))
m2.pre_match #=> "root:x…(snip)"
m2.begin(0) #=> 1615
大手町.rb #17 「Ruby の正規表現について」
今回扱わなかったトピック
正規表現はとても奥が深く、今回は時間の関係もあり、
省略した話題が数多くあります。
興味がある方は自分で調べてください。
後方参照
特殊変数($`、$'、$1、$2 など)
名前付きキャプチャ
Unicodeプロパティ
アトミックグループ
部分式呼び出し(subexpression call)
先読み、後読み
条件分岐
非包含オペレータ
16
大手町.rb #17 「Ruby の正規表現について」
まとめ
正規表現は文字列へのマッチ、ログ処理等でとても役立つ
正規表現を使う上で特に利用頻度が高いものを中心に
さまざまなノウハウを紹介
複雑な正規表現を作るときは
正規表現の visualizer ツールで、ロジックを確認したり
refiddle などでマッチするかどうかを確認したり
いきなり複雑な正規表現を作ろうとせず、段階的に構築しましょう
Regexp.escape
Regexp.union
正規表現の式展開 /#{regexp}/
17
ご清聴ありがとう
ございました

More Related Content

More from Tomoya Kawanishi

ENECHANGE社での Scout APM 利用事例
ENECHANGE社での Scout APM 利用事例ENECHANGE社での Scout APM 利用事例
ENECHANGE社での Scout APM 利用事例Tomoya Kawanishi
 
エンジニア転職のノウハウ
エンジニア転職のノウハウエンジニア転職のノウハウ
エンジニア転職のノウハウTomoya Kawanishi
 
Ruby on Rails のキャッシュ機構について
Ruby on Rails のキャッシュ機構についてRuby on Rails のキャッシュ機構について
Ruby on Rails のキャッシュ機構についてTomoya Kawanishi
 
Ruby初心者からよく質問されること
Ruby初心者からよく質問されることRuby初心者からよく質問されること
Ruby初心者からよく質問されることTomoya Kawanishi
 
AWS のコスト管理をちゃんとしたくてやったこと
AWS のコスト管理をちゃんとしたくてやったことAWS のコスト管理をちゃんとしたくてやったこと
AWS のコスト管理をちゃんとしたくてやったことTomoya Kawanishi
 
PostgreSQL のイケてるテクニック7選
PostgreSQL のイケてるテクニック7選PostgreSQL のイケてるテクニック7選
PostgreSQL のイケてるテクニック7選Tomoya Kawanishi
 
HTTPと Webクローリングについて
HTTPと WebクローリングについてHTTPと Webクローリングについて
HTTPと WebクローリングについてTomoya Kawanishi
 
Active record query interface
Active record query interfaceActive record query interface
Active record query interfaceTomoya Kawanishi
 
Active Support のコア拡張機能について
Active Support のコア拡張機能についてActive Support のコア拡張機能について
Active Support のコア拡張機能についてTomoya Kawanishi
 
Ruby ビジネス創出展 Ruby初心者向けプログラミングセミナー
Ruby ビジネス創出展 Ruby初心者向けプログラミングセミナーRuby ビジネス創出展 Ruby初心者向けプログラミングセミナー
Ruby ビジネス創出展 Ruby初心者向けプログラミングセミナーTomoya Kawanishi
 
RubyのDir、File、IO について
RubyのDir、File、IO についてRubyのDir、File、IO について
RubyのDir、File、IO についてTomoya Kawanishi
 
Thread の利用事例紹介
Thread の利用事例紹介Thread の利用事例紹介
Thread の利用事例紹介Tomoya Kawanishi
 
Ruby の制御構造とリテラルについて
Ruby の制御構造とリテラルについてRuby の制御構造とリテラルについて
Ruby の制御構造とリテラルについてTomoya Kawanishi
 
RubyGems と Bundler について
RubyGems と Bundler についてRubyGems と Bundler について
RubyGems と Bundler についてTomoya Kawanishi
 
Ruby on Rails プロジェクトでの他言語エコシステムとの共存方法
Ruby on Rails プロジェクトでの他言語エコシステムとの共存方法Ruby on Rails プロジェクトでの他言語エコシステムとの共存方法
Ruby on Rails プロジェクトでの他言語エコシステムとの共存方法Tomoya Kawanishi
 
マークアップで使えるRuby
マークアップで使えるRubyマークアップで使えるRuby
マークアップで使えるRubyTomoya Kawanishi
 
エネチェンジでの Side ci 利用事例について
エネチェンジでの Side ci 利用事例についてエネチェンジでの Side ci 利用事例について
エネチェンジでの Side ci 利用事例についてTomoya Kawanishi
 
AWSコストの事業部別コスト配分について
AWSコストの事業部別コスト配分についてAWSコストの事業部別コスト配分について
AWSコストの事業部別コスト配分についてTomoya Kawanishi
 

More from Tomoya Kawanishi (20)

英単語の覚え方
英単語の覚え方英単語の覚え方
英単語の覚え方
 
ENECHANGE社での Scout APM 利用事例
ENECHANGE社での Scout APM 利用事例ENECHANGE社での Scout APM 利用事例
ENECHANGE社での Scout APM 利用事例
 
エンジニア転職のノウハウ
エンジニア転職のノウハウエンジニア転職のノウハウ
エンジニア転職のノウハウ
 
Ruby on Rails のキャッシュ機構について
Ruby on Rails のキャッシュ機構についてRuby on Rails のキャッシュ機構について
Ruby on Rails のキャッシュ機構について
 
Ruby初心者からよく質問されること
Ruby初心者からよく質問されることRuby初心者からよく質問されること
Ruby初心者からよく質問されること
 
AWS のコスト管理をちゃんとしたくてやったこと
AWS のコスト管理をちゃんとしたくてやったことAWS のコスト管理をちゃんとしたくてやったこと
AWS のコスト管理をちゃんとしたくてやったこと
 
PostgreSQL のイケてるテクニック7選
PostgreSQL のイケてるテクニック7選PostgreSQL のイケてるテクニック7選
PostgreSQL のイケてるテクニック7選
 
HTTPと Webクローリングについて
HTTPと WebクローリングについてHTTPと Webクローリングについて
HTTPと Webクローリングについて
 
Rake
RakeRake
Rake
 
Active record query interface
Active record query interfaceActive record query interface
Active record query interface
 
Active Support のコア拡張機能について
Active Support のコア拡張機能についてActive Support のコア拡張機能について
Active Support のコア拡張機能について
 
Ruby ビジネス創出展 Ruby初心者向けプログラミングセミナー
Ruby ビジネス創出展 Ruby初心者向けプログラミングセミナーRuby ビジネス創出展 Ruby初心者向けプログラミングセミナー
Ruby ビジネス創出展 Ruby初心者向けプログラミングセミナー
 
RubyのDir、File、IO について
RubyのDir、File、IO についてRubyのDir、File、IO について
RubyのDir、File、IO について
 
Thread の利用事例紹介
Thread の利用事例紹介Thread の利用事例紹介
Thread の利用事例紹介
 
Ruby の制御構造とリテラルについて
Ruby の制御構造とリテラルについてRuby の制御構造とリテラルについて
Ruby の制御構造とリテラルについて
 
RubyGems と Bundler について
RubyGems と Bundler についてRubyGems と Bundler について
RubyGems と Bundler について
 
Ruby on Rails プロジェクトでの他言語エコシステムとの共存方法
Ruby on Rails プロジェクトでの他言語エコシステムとの共存方法Ruby on Rails プロジェクトでの他言語エコシステムとの共存方法
Ruby on Rails プロジェクトでの他言語エコシステムとの共存方法
 
マークアップで使えるRuby
マークアップで使えるRubyマークアップで使えるRuby
マークアップで使えるRuby
 
エネチェンジでの Side ci 利用事例について
エネチェンジでの Side ci 利用事例についてエネチェンジでの Side ci 利用事例について
エネチェンジでの Side ci 利用事例について
 
AWSコストの事業部別コスト配分について
AWSコストの事業部別コスト配分についてAWSコストの事業部別コスト配分について
AWSコストの事業部別コスト配分について
 

Recently uploaded

AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdfAWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdfFumieNakayama
 
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)UEHARA, Tetsutaro
 
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineerYuki Kikuchi
 
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)NTT DATA Technology & Innovation
 
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...博三 太田
 
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdfクラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdfFumieNakayama
 
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案sugiuralab
 
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?akihisamiyanaga1
 
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)Hiroshi Tomioka
 

Recently uploaded (9)

AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdfAWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
 
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
 
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
 
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
 
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
 
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdfクラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
 
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
 
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
 
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
 

Ruby の正規表現について

  • 2. 大手町.rb #17 「Ruby の正規表現について」 1自己紹介 Tomoya Kawanishi a.k.a. @cuzic エネチェンジ株式会社 チーフエンジニア 電力会社、ガス会社を切り替えるなら、エネチェンジ経由で! 一般家庭も!法人も! Ruby関西の中の人 2019年7月13日(土) 第87回Ruby関西勉強会 2019年9月15日(日) 大阪RubyKaigi 02 発表者として登壇くださる方、あとで声かけください。 大手町.rb の中の人 毎月 大手町.rb の開催を予定 東京駅、各線大手町駅から直結! Ruby の初級者がメインターゲット
  • 3. 大手町.rb #17 「Ruby の正規表現について」 今日のテーマ Ruby の正規表現について 正規表現という用語について 英語の Regular Expression の日本語訳 言語学では「正則表現」 expression は「表現」以外に「式」という意味もある 違和感があるが、いまさらどうしようもない 正規表現はなぜ重要か 正規表現を使うと 特定の文字列にマッチするかどうかの判定ができる 文字列の一部を取得(capture)することがカンタンにできる ログ処理、テキストバリデーションなどがカンタンにできる 特徴 ほぼすべての言語で実装されており、応用範囲が幅広い 非常にコンパクトに記述でき、可読性、メンテナンス性が高い 知る人ぞ知る機能も多いがベンリ 2
  • 4. 大手町.rb #17 「Ruby の正規表現について」 正規表現の作り方 /hoge/ のように / で正規表現を作るのが一般的 中に / があるときは %r 記法を使う 正規表現にしたい文字列を引数で受け取るときなどは Regexp.new を使うこともある / や %r の中では 式展開 #{} を使うこともできる 3 /hoge/ : もっとも一般的 %r(https://enechange¥.jp) # % 記法。 Regexp.new("https://enechange¥¥.jp") # Regexp.new Regexp.compile("https://enechange¥¥.jp") # Regexp.compile production_domain = "enechange¥¥.jp" %r(https://#{production_domain})
  • 5. 大手町.rb #17 「Ruby の正規表現について」 正規表現の例 正規表現を使うと、文字列マッチが簡単にできる ^ : アンカーの一つ。行頭にマッチする () : 正規表現の一部をキャプチャするときに使う . : メタ文字の1つ。改行を除く任意の1文字にマッチ + : メタ文字の1つ。直前の部分式を1回以上の繰り返し にマッチ 4 url = "https://enechange.jp/try/input" # / を使った正規表現リテラル。 マッチした position を返す。 url =~ /^https:¥/¥/enechange¥.jp/(.+)/ #=> 0 $1 #=> "try/input" # %r を使った正規表現リテラル url =~ %r(^https://enechange¥.jp/(.+)) # String#match? を使うと true false を返す url.match?(%r(¥Ahttps://enechange¥.jp/(.+)))
  • 6. 大手町.rb #17 「Ruby の正規表現について」 正規表現visualizer Regulex という正規表現の visualizer がある。 慣れないうちは visualizer を使って、 その正規表現がどういう処理になるかを確認しながら、 進めると良い 5 # %r を使った正規表現リテラル url =~ %r(^https://enechange¥.jp/(.+))
  • 7. 大手町.rb #17 「Ruby の正規表現について」 正規表現を学ぶときのコツ 正規表現は仕様が膨大 すべてを最初から理解して使いこなす必要はない 業務で必要になる都度、少しずつ理解している範囲を広 げるといい 正規表現の練習用サイトもある https://regexone.com/ https://www.hackerrank.com/domains/regex 正規表現マッチを簡単に確認できるサイトもある http://refiddle.com/ https://rubular.com/ いろいろ既存サービスを使いこなして、上達を目指しま しょう 6
  • 8. 大手町.rb #17 「Ruby の正規表現について」 文字マッチ 7 . : 改行を除く任意の1文字 ¥から始まらない文字 a など : a にマッチ ¥n : 改行にマッチ ¥記号 ¥/ ¥. など : その記号1文字にマッチ ¥w : 単語構成文字。 英小文字、英大文字、数字、アンダースコア、a-zA-Z0-9_ ¥s : 空白文字。半角空白、タブ、改行、ほか [ ¥t¥r¥n¥f¥v] ¥d : 0から9 の数字 [abc] : 文字 a か b か c [0-3] : 文字、 0 1 2 3 にマッチ "2019-05-15".match?(/20¥d¥d-[01]¥d-[0-3]¥d/) "example@example.jp".match?(/[-.¥w]+@)[-.¥w]+¥.jp/)
  • 9. 大手町.rb #17 「Ruby の正規表現について」 アンカー 8 ^ : 行頭にマッチ $ : 行末にマッチ ¥A : 文字列の先頭にマッチする ¥Z : 文字列の末尾にマッチ。ただし、改行が最後にあるときはその直前にマッチ。 ¥z : 文字列の末尾にマッチする。 ¥b : 単語の境界にマッチする body = File.read("/etc/passwd") body =~ /root/ #=> 0 body =~ /nobody/ #=> 818 body =~ /¥Aroot/ #=> 0 body =~ /¥Anobody/ #=> nil body =~ /bash$/ #=> 27 body =~ /bash¥Z/ #=> 2248 body =~ /bash¥z/ #=> nil アンカーとは 幅0 の文字列にマッチするメタ文字列
  • 10. 大手町.rb #17 「Ruby の正規表現について」 繰り返し、量指定子 9 * : 0回以上 + : 1回以上 ? : 0回もしくは1回 {n} :ちょうどn回(nは数字) {n,} : n回以上(nは数字) {,m} : m回以下(mは数字) {n,m} : n回以上m回以下(n,mは数字) 直前の部分式を何回繰り返すかを指定する 欲張り(greedy)マッチ。最長の文字列にマッチする "2019-05-15".match?(/¥d{4}-¥d¥d?-¥d¥d?/) "2019-05-15".match?(/¥d{4}(-¥d{1,2}){2}/) # /¥d{4}-¥d{1,2}-¥d{1,2}/ と同じ。 '<a href="#">'.match?(/¥<a¥s+href='?"?#'?"?¥s*¥>/) m = '<div><a href="#">top</a></div>'.match(/<.+>/) m[0] #=> "<div><a href=¥"#¥">top</a></div>" m = /^.*(¥d+)¥./.match("Copyright 2013.") m[1] #=> 3
  • 11. 大手町.rb #17 「Ruby の正規表現について」 最小量指定子 直前の部分式を何回繰り返すかを指定する 最短の文字列にマッチする 10 *? : 0回以上 +? : 1回以上 ?? : 0回もしくは1回 {n}? :ちょうどn回(nは数字) {n,}? : n回以上(nは数字) {,m}? : m回以下(mは数字) {n,m}? : n回以上m回以下(n,mは数字) m = '<div><a href="#">top</a></div>'.match(/¥<.+?¥>/) m[0] #=> "<div>" m = /^.*?(¥d+)¥./.match("Copyright 2013.") m[1] #=> 2013
  • 12. 大手町.rb #17 「Ruby の正規表現について」 キャプチャ 丸括弧()で、キャプチャできる 11 regex = %r(¥<a href="(.+?)".*?>(.+?)</a>) m = '<div><a href="#">top</a></div>'.match(regex) m[1] #=> "#" m[2] #=> "top"
  • 13. 大手町.rb #17 「Ruby の正規表現について」 いずれかへのマッチ 縦棒(パイプ) | で、複数の正規表現のどれかにマッ チするかどうかという判定ができる 凝った正規表現を書くよりは、 | で分割する方が分かりやすいこともある 12 request.fullpath.match?(%r(¥A/(login|logout))) # "/login" や "/logout" 、 "/login?from=blahblah" などにマッチする message =~ /([0-9a-zA-Z]|[0-9a-zA-Z])+/
  • 14. 大手町.rb #17 「Ruby の正規表現について」 正規表現関連のメソッド (String クラス) 13 # String#[regex] : 正規表現にマッチした文字列を返す "We are hiring"[/¥b¥w+$/] #=> "hiring" # String#[regex, index] : 正規表現にマッチし、その index のキャプチャ文字列を返す "We are hiring"[/.+¥b(¥w+)$/, 1] #=> "hiring" # String#=~ : 正規表現とマッチした position を返す "We are hiring" =~ /¥b(¥w+)$/ #=> 7 # String#match : 正規表現とマッチした MatchData オブジェクトを返す "We are hiring".match(/¥b(¥w+)$/) #=> #<MatchData "hiring" 1:"hiring"> body = File.read("/etc/passwd") index = body =~ /bash$/ body.match(/^.+bash$/, index) # index 文字目からサーチを開始する # String#match? : マッチ結果を true、 false で返す。動作が速い。 "We are hiring".match?(/¥b(¥w+)$/) #=> true String クラスで正規表現関連で特に有用なメソッドを 5つ紹介します
  • 15. 大手町.rb #17 「Ruby の正規表現について」 正規表現関連のメソッド (Regexp クラス) 14 # Regexp.quote : 正規表現をエスケープする prod_url = "https://enechange.jp" /¥b#{prod_url}¥b/ =~ "https://enechangeejp" #=> 0 マッチする /¥b#{Regexp.quote(prod_url)}¥b/ =~ "https://enechangeejp" #=> nil。マッチしない。 # Regexp.union( pat1, pat2, …) : 引数のいずれかにマッチする正規表現を返す # 複雑な正規表現を段階的に構築したいときに便利 re_letter = Regexp.union(/[0-9a-zA-Z]/, /[0-9A-Za-z]/) message =~ /#{re_letter}+/ # Regexp#match、 Regexp#match? : String クラスの対応するメソッドと同じ Regexp クラスで正規表現関連で特に有用なメソッドを 3つ紹介します
  • 16. 大手町.rb #17 「Ruby の正規表現について」 正規表現関連のメソッド (MatchData クラス) 15 body = File.read("/etc/passwd") m = body.match(/.+:(.+?sh)$/) # MatchData#captures で括弧 () でキャプチャした文字列を配列で取得できる m.captures #=> ["/bin/bash"] # MatchData#[] でマッチした文字列を配列のようにアクセスできる m[0] #=> "root:x:0:0:root:/root:/bin/bash" m[1] = "/bin/bash" m.pre_match #=> "" m.post_match #=> "¥ndaemon:…(snip)" # MatchData#begin(index) で index に対応する要素の開始位置が分かる m.begin(0) #=> 0 m.begin(1) #=> 22 # MatchData#end(index) で index に対応する要素の終了位置が分かる m.end(0) #=> 31 m.end(1) #=> 31 m2 = body.match(/.+:(.+?sh)$/, m.end(0)) m2.pre_match #=> "root:x…(snip)" m2.begin(0) #=> 1615
  • 17. 大手町.rb #17 「Ruby の正規表現について」 今回扱わなかったトピック 正規表現はとても奥が深く、今回は時間の関係もあり、 省略した話題が数多くあります。 興味がある方は自分で調べてください。 後方参照 特殊変数($`、$'、$1、$2 など) 名前付きキャプチャ Unicodeプロパティ アトミックグループ 部分式呼び出し(subexpression call) 先読み、後読み 条件分岐 非包含オペレータ 16
  • 18. 大手町.rb #17 「Ruby の正規表現について」 まとめ 正規表現は文字列へのマッチ、ログ処理等でとても役立つ 正規表現を使う上で特に利用頻度が高いものを中心に さまざまなノウハウを紹介 複雑な正規表現を作るときは 正規表現の visualizer ツールで、ロジックを確認したり refiddle などでマッチするかどうかを確認したり いきなり複雑な正規表現を作ろうとせず、段階的に構築しましょう Regexp.escape Regexp.union 正規表現の式展開 /#{regexp}/ 17