30
7正規表現 JavaScript The Good Parts』読書会 2013/04/11 @torazuka

JavaScript The Good Parts Chapter 7

Embed Size (px)

DESCRIPTION

社内読書会での発表資料。

Citation preview

Page 1: JavaScript The Good Parts Chapter 7

7章 正規表現『JavaScript The Good Parts』読書会

2013/04/11 @torazuka

Page 2: JavaScript The Good Parts Chapter 7

(おまけ)実行環境

• Node.js

• mocha

• expect.js

• Sublime Text 2

•サンプルコード• https://bitbucket.org/torazuka/learning_jsgp

Page 3: JavaScript The Good Parts Chapter 7

今回の範囲「7章正規表現」

7.1 正規表現の例7.2 正規表現の構築7.3 正規表現の構成要素

Page 4: JavaScript The Good Parts Chapter 7

JavaScriptの正規表現

regexp.execregexp.teststring.matchstring.replacestring.searchstring.split → くわしくは8章で

文字列操作より正規表現を使った方がパフォーマンスが良いことが多い

正規表現が利用できるメソッド

正規表現はメンテナンスやデバッグが難しくなりやすいため,本章では著者が単純化したルールを紹介する簡潔さを多少犠牲にする代わりに,多少簡単に扱えるように

Page 5: JavaScript The Good Parts Chapter 7

7.1正規表現の例 (その1)

/^(?:([A-Za-z]+):)?(¥/{0,3})([0-9.¥-A-Za-z]+)(?::(¥d+))?(?:¥/([^?#]*))?(?:¥?([^#]*))?(?:#(.*))?$/

1行で記述する (上の正規表現リテラルは本来1行で書く)

空白が意味を持つ (テキトーに空白を入れてはいけない)

URIをマッチするための正規表現:

Page 6: JavaScript The Good Parts Chapter 7

7.1正規表現の例―全体

/^(?:([A-Za-z]+):)?(¥/{0,3})([0-9.¥-A-Za-z]+)(?::(¥d+))?(?:¥/([^?#]*))?(?:¥?([^#]*))?(?:#(.*))?$/

/…/が正規表現の全体

^は文字列のはじまり,$は文字列のおわり余計なものが最初,あるいは最後に付いていないことを保証する

(…)はキャプチャグループマッチした文字列を配列に格納する.最初のindexは1キャプチャグループ末尾の?は,そのキャプチャグループを省略可能という意味

Page 7: JavaScript The Good Parts Chapter 7

7.1正規表現の例― http:

/^(?:([A-Za-z]+):)?(¥/{0,3})([0-9.¥-A-Za-z]+)(?::(¥d+))?(?:¥/([^?#]*))?(?:¥?([^#]*))?(?:#(.*))?$/

[…]は文字クラス

:はコロン文字

(?:…)は非キャプチャグループマッチした文字列を配列に格納しない.使わない文字列は,非キャプチャグループにするとパフォーマンス上よい

-は範囲を表わす.上の場合,AからZとaからzにマッチする

+は直前の文字クラスが1回以上出てくるときにマッチする

Page 8: JavaScript The Good Parts Chapter 7

7.1正規表現の例― ///

/^(?:([A-Za-z]+):)?(¥/{0,3})([0-9.¥-A-Za-z]+)(?::(¥d+))?(?:¥/([^?#]*))?(?:¥?([^#]*))?(?:#(.*))?$/

{0,3}は直前の文字が0回,1回,2回,3回連続するとマッチする

(…)はキャプチャグループ

¥/はスラッシュ文字正規表現の終わりでないことを示すためエスケープする

Page 9: JavaScript The Good Parts Chapter 7

7.1正規表現の例― www.ora.com

/^(?:([A-Za-z]+):)?(¥/{0,3})([0-9.¥-A-Za-z]+)(?::(¥d+))?(?:¥/([^?#]*))?(?:¥?([^#]*))?(?:#(.*))?$/

(…)はキャプチャグループ

.はピリオド文字¥-はハイフン文字範囲を表わすハイフンでないことを示すためエスケープする

+は直前の文字クラスが1回以上出てくるときにマッチする

Page 10: JavaScript The Good Parts Chapter 7

7.1正規表現の例― :80

/^(?:([A-Za-z]+):)?(¥/{0,3})([0-9.¥-A-Za-z]+)(?::(¥d+))?(?:¥/([^?#]*))?(?:¥?([^#]*))?(?:#(.*))?$/

(?:…)は非キャプチャグループ末尾に?があるので省略可能

2つ目の:はコロン文字

+は直前の文字クラスが1回以上出てくるときにマッチする

¥dは数字

Page 11: JavaScript The Good Parts Chapter 7

7.1正規表現の例― /goodparts

/^(?:([A-Za-z]+):)?(¥/{0,3})([0-9.¥-A-Za-z]+)(?::(¥d+))?(?:¥/([^?#]*))?(?:¥?([^#]*))?(?:#(.*))?$/

(?:…)は非キャプチャグループ末尾に?があるので省略可能

¥/はスラッシュ文字

*は直前の文字クラスの0回または1回以上の繰り返しにマッチする

^?#は「?と#を除くすべての文字」

Page 12: JavaScript The Good Parts Chapter 7

7.1正規表現の例― ?q

/^(?:([A-Za-z]+):)?(¥/{0,3})([0-9.¥-A-Za-z]+)(?::(¥d+))?(?:¥/([^?#]*))?(?:¥?([^#]*))?(?:#(.*))?$/

(?:…)は非キャプチャグループ末尾に?があるので省略可能

¥?は?文字

*は直前の文字クラスの0回または1回以上の繰り返しにマッチする

^#は「#を除くすべての文字」

Page 13: JavaScript The Good Parts Chapter 7

7.1正規表現の例― #fragment

/^(?:([A-Za-z]+):)?(¥/{0,3})([0-9.¥-A-Za-z]+)(?::(¥d+))?(?:¥/([^?#]*))?(?:¥?([^#]*))?(?:#(.*))?$/

(?:…)は非キャプチャグループ末尾に?があるので省略可能

#はシャープ文字

*は直前の文字クラスの0回または1回以上の繰り返しにマッチする

.は「改行文字以外のすべての文字」

Page 14: JavaScript The Good Parts Chapter 7

7.1正規表現の例―良い正規表現

正規表現の機能は,各処理系の間で互換性が低い入れ子部分の実行速度が遅い処理系もある複雑さを避けることは大事

• 短く,シンプルに• 正しく動くと確信できる• 必要なときに修正できる

Page 15: JavaScript The Good Parts Chapter 7

7.1正規表現の例 (その2)

/^-?¥d+(?:¥.¥d*)?(?:e[+¥-]?¥d+)?$/i

さっきより短い!ガンバ!

数字をマッチするための正規表現:

Page 16: JavaScript The Good Parts Chapter 7

7.1正規表現の例 (その2)

/^-?¥d+(?:¥.¥d*)?(?:e[+¥-]?¥d+)?$/i

/^…$/でテキスト全体が正規表現の適用範囲となる“もしこれらを付けなかった場合は、この正規表現は文字列の中に数値が含まれているかどうかを調べるものになる”

iはアルファベットの大文字小文字を区別しないためのフラグここでは,eとEを両方マッチさせるために使っている[Ee]や(?:E|e)でも同じことができるが,iフラグを使う方が簡潔

Page 17: JavaScript The Good Parts Chapter 7

7.1正規表現の例 (その2)

/^-?¥d+(?:¥.¥d*)?(?:e[+¥-]?¥d+)?$/i

-?は,ハイフン文字を省略できるという意味

¥dは数字. [0-9]と同じ

+は直前の文字クラスが1回以上出てくるときにマッチする

Page 18: JavaScript The Good Parts Chapter 7

7.1正規表現の例 (その2)

/^-?¥d+(?:¥.¥d*)?(?:e[+¥-]?¥d+)?$/i

¥. はピリオド文字.ここでは小数点にマッチさせる意図

¥dは数字

*は直前の文字クラスの0回または1回以上の繰り返しにマッチする

(?:…)は非キャプチャグループマッチした文字列を配列に格納しない.

Page 19: JavaScript The Good Parts Chapter 7

7.1正規表現の例 (その2)

/^-?¥d+(?:¥.¥d*)?(?:e[+¥-]?¥d+)?$/i

+¥-は正負記号

¥dは数字

(?:…)は非キャプチャグループ

eはアルファベットのe

+は直前の文字クラスが1回以上出てくるときにマッチする

Page 20: JavaScript The Good Parts Chapter 7

7.2正規表現の構築

RegExpオブジェクトを生成する方法

1. 正規表現リテラルを利用 (推奨)2. RegExpコンストラクタ関数を利用

プログラミング時に確定できないデータを使って,実行時に正規表現を生成する場合に便利

• 2の方法を使うとき,バックスラッシュとダブルクォーテーションとクォーテーションは,エスケープする必要がある

• 同じ正規表現リテラルで生成されたRegExpオブジェクトは,単一のインスタンスを共有する

留意点

Page 21: JavaScript The Good Parts Chapter 7

7.2正規表現の構築

正規表現リテラルのフラグ• g 複数回マッチする• i大文字と小文字を区別しない• m ^と$が行末記号にマッチする ?

RegExpオブジェクトのプロパティ

• global(役割はフラグgに同じ)• ignoreCase(フラグiに同じ)• muitiline(フラグmに同じ)• lastIndex次回のexecメソッドのマッチの開始点.初期値は0• source ソース文字列

複数行に渡るマッチ対象を扱える(例: import文や設定ファイルなど)

Page 22: JavaScript The Good Parts Chapter 7

7.3正規表現の構成要素

7.3.1 選択肢

7.3.2正規表現シーケンス

7.3.2正規表現シーケンス

7.3.3正規表現因子

7.3.3正規表現因子

Page 23: JavaScript The Good Parts Chapter 7

7.3.1 選択肢

|(タテ棒)で分割された1つ以上の正規表現シーケンスが,選択肢を構成するいずれかのシーケンスにマッチするとき,その正規表現にマッチする書かれた順にチェックされる

Page 24: JavaScript The Good Parts Chapter 7

7.3.2 正規表現シーケンス

1つ以上の正規表現因子が,正規表現シーケンスを構成する

因子がいくつ続くかを数量詞で示す(c.f. 7.3.8)数量詞が指定されていないときは1個とみなす

Page 25: JavaScript The Good Parts Chapter 7

7.3.3正規表現因子

• 文字• カッコで囲まれたグループ• 文字クラス• エスケープシーケンス

数字とアルファベット以外は,直前に¥をつけることで,その文字自身とみなす

ピリオド,キャロット,ドル文字は,エスケープしない場合に次の意味を持つ

• . 改行文字以外の文字• ^ lastIndexが0 のとき,テキストの先頭部分にマッチする

mフラグがセットされているときは,改行文字にもマッチする• $ テキストの末尾部分にマッチする

mフラグがセットされているときは,改行文字にもマッチする

Page 26: JavaScript The Good Parts Chapter 7

7.3.4エスケープ

• ¥f改ページ• ¥n改行文字• ¥r キャリッジリターン• ¥t タブ文字• ¥u ユニコード文字の16進数表現• ¥b バックスペース

• ¥d数字,¥D数字以外• ¥s空白文字,¥S 空白文字以外

• ¥w [0-9A-Za-z_]と同じ• ¥b 単語境界

多言語アプリケーションでは実用的でないので,用途に応じたものを自分で定義する(¥wと¥bは良いパーツではない)

• ¥1第1番目のキャプチャグループ

Page 27: JavaScript The Good Parts Chapter 7

7.3.5正規表現グループ

• キャプチャグループ(...) マッチした文字列はキャプチャ(配列に格納)される• 非キャプチャグループ(?:...) されない

• 肯定先読み(?=...) グループにマッチした後,走査位置を巻き戻す• 否定先読み(?!...) グループのマッチに失敗した場合のみ走査を続行する

次の2つは「良いパーツ」ではない

→サンプルコード参照

Page 28: JavaScript The Good Parts Chapter 7

7.3.6正規表現クラス

• [...] 文字のセットを表わす

• 簡潔に書ける

• (?:a|e|i|o|u)

• [aeiou]

• 文字の範囲を指定できる

• (?:!|"|#|¥$|%|&|'|¥(|¥)|¥*|¥+|,|-|¥.|¥/|:|;|<|=|>|@|¥[|¥¥|]|¥^|_|` |¥{|¥||¥}|~)

• [!-¥/:-@¥[-`{-~]

• 補集合を表現できる

• [^ではじめる

便利な点

Page 29: JavaScript The Good Parts Chapter 7

7.3.7正規表現クラスにおけるエスケープ

「正規表現因子におけるエスケープ」との違いに注意

¥bはバックスペースを表わす

次の文字は正規表現クラスの中ではエスケープしなければならない

- / [ ¥ ] ^

Page 30: JavaScript The Good Parts Chapter 7

7.3.8数量詞

正規表現因子の後につけて,因子がいくつ連続したときにマッチするかを示す

マッチの処理は貪欲.数量詞の後ろに?をつけると貪欲でなくなる

/www//w{3}/ // 上と同じ

/w{3, 6}/ // wが3~6回連続したときにマッチする/w{0,}/ // *と同じ/w{1,}/ // +と同じ