正規表現 入門
● 2009/06/06
● mollifier
● http://d.hatena.ne.jp/mollifier/
正規表現って何 ?
こんなの
ウェブテコ第 [0-9]+ 回
こんなことはありませんか ?
表記の揺れを考慮して検索したい
僕は Internet Explorer が大好きです。それは、 InternetExplorer が僕にちょうど良いスピードで動いてくれるからです。
それに、他では学べない IE独自の技術も勉
強できるからです。
<h1> トマトとチキンの煮込み </h1><h2> 材料 </h2><ul> <li> トマトの水煮 </li> <li> 鶏もも肉 </li></ul>
HTML ファイルから <h*>( 見出し要素 ) の行だけ探したい
こんな時に役に立つのが正規表現
正規表現とは
● 文字列のパターンを表現する方法● 複雑な条件でも簡潔に表記できる
正規表現が使用可能なツール● テキストエディタ
– 秀丸– サクラエディタ– TextMate– vim– emacs
など
正規表現が使用可能なツール● プログラム言語
– JavaScript– Perl– Ruby– Java– C#
など
こんなものにも
http://www.google.co.jp/codesearch
テキストを扱うツールならたいてい使用できる
ということは ……
一度身につけるといろんな場面で活用できる
ぜひとも使えるようになりたい
というわけで、正規表現の使い方を見ていきましょう
再び さっきの例
ウェブテコ第 [0-9]+ 回
ウェブテコ第 [0-9]+ 回
この [0-9]+ という部分は正規表現で特別な意味を持つ
このような文字をメタ文字と呼びます
メタ文字の意味を理解するのが大事
メタ文字一覧● {n,m}
● {n,}
● {n}
● ?
● +
● *
● [...]
● [^...]
● .
● \w
● \W
● \s
● \S
● \d
● \D
● \t
● \n
● \r
まだまだあります● |
● (pattern)
● (?:pattern)
● ^
● $
● \b
● \B
● (?=pattern)
● (?!pattern)
● *?
● +?
● ??
● {n,m}?
● {n,}?
● {n}?
Never Ending● \A
● \Z
● \z
● \G
● (?#...)
● (?<=pattern)
● (?<!pattern)
● (?>pattern)
● (?<name>pattern)
● (?ipattern)
● *+
● ++
● ?+
● {n,m}+
● {n,}+
● {n}+
いっぱいありすぎ
でも、よく使うのはごく一部
よく使うもの その 1
● . ( ドット )
– 任意の 1 文字● [...]
– [ ] 内の任意の 1 文字● [^...]
– [ ] 内に含まれない任意の 1 文字
. ( ドット ) を使う例
ミッキー .ウス
ミッキー .ウス
● マッチする–ミッキーガウス
● マッチしない–ミッキーママウス
[...] を使う例
今日は [456] 月です
今日は [456] 月です
● マッチする–今日は 6月です
● マッチしない–今日は 3月です
[ - ] で範囲の指定
今日は [0-9] 日です
今日は [0-9]日です
● マッチする–今日は 6日です
● マッチしない–今日は 10日です
–今日は祝日です
[^...] を使う例
今日は [^0][0-9] 日です
今日は [^0][0-9] 日です
● マッチする–今日は 10日です
● マッチしない–今日は 06日です
これらはすべて「何か 1 文字」 にマッチする
よく使うもの その 2
● *
– 直前の項目を 0 回以上繰り返す● +
– 直前の項目を 1 回以上繰り返す
* を使う例
url *=( スペースの後に *)
url *=
● マッチする– url=”http://webteko.jp/”;
– url =”http://webteko.jp/”;
– url =”http://webteko.jp/”;
● マッチしない– url;
+ を使う例
<div +class=”main”( スペースの後に +)
<div +class=”main”
● マッチする– <div class=”main”
– <div class=”main”
● マッチしない– <divclass=”main”
これらはすべて繰り返し回数を指定する
よく使うもの その 3
● ^
– 行の先頭● $
– 行のの最後
^ を使う例
^[0-9]
^[0-9]
● マッチする– 3.2 文字列
● マッチしない– Opera 10 ベータ版が
リリースされました
$ を使う例
^[0-9]+$
^[0-9]+$
● マッチする– 0
– 177
● マッチしない– 1,000
これらはすべて位置にマッチする
位置を固定するところから「アンカー」とも呼ばれる
ここまでのまとめ
何か 1 文字にマッチする
●. ( ドット )●[...]●[^...]
繰り返し回数を指定する
●*●+
位置にマッチする( アンカー )
●^●$
この 7 種類だけでもかなり凝ったことが出来る
他にも色々メタ文字があるけど基本は同じ
この 3 種類のどれか
● 何か 1 文字にマッチする● 繰り返し回数を指定する● 位置にマッチする
メタ文字一覧とかを見ながら使ってみてください
ここからが本番
正規表現処理のしくみ
正規表現マッチングのメカニズムについて、もう少し詳しく見
てみましょう
例題
パス名からディレクトリ部分を取り除きたい
● /etc/hosts -> hosts● /usr/bin/zsh -> zsh
いきなり答え
こんな風に置換すれば OK
● 検索する文字列^.*/
● 置換する文字列空文字列
/usr/bin/zsh
下線部が ^.*/ にマッチする
ん ? でも
何通りにも解釈できるんですけど
1./usr/bin/zsh
2./usr/bin/zsh
3./usr/bin/zsh
^.*/
結局どれ ?
マッチング処理を最初から順番に見てみる
/usr/bin/zsh
^ . */
開始位置が先頭に固定される
/usr/bin/zsh
^ .* /
先頭の / が .* にマッチする
もうちょっと詳しい説明
● .* の繰り返し回数は「何回でも良い」
もうちょっと詳しい説明
● なので、 .* にとっては/ を「掴む」か「掴まない」か2 つ選択肢がある
もうちょっと詳しい説明
● そういうときは「掴む」方を選ぶ● つまり長くなる方を選ぶ● この動作を「欲張り」と呼ぶ
/usr/bin/zsh
^ .* /
次の u も .* にマッチする
/usr/bin/zsh
^ .* /
どんどんマッチする
/usr/bin/zsh
^ .* /
結局、全部 .* にマッチする
/usr/bin/zsh
^ .* /
最後の / にマッチする文字がない
ない
じゃあ、マッチ失敗 ?
いやいや、そうじゃない
● .* は「任意の回数」のなので、最後まで掴まなくても良い
いやいや、そうじゃない● .* が最後の h を「掴む」ことを選らんだら、全体としてマッチに失敗した
いやいや、そうじゃない● .* が最後の h を「掴む」ことを選らんだら、全体としてマッチに失敗した
● .* が h を「掴まない」方を選んでみる
/usr/bin/zsh
^ .* /
1 文字手放す
/usr/bin/zsh
^ .* /
これでもマッチ失敗
/usr/bin/zsh
^ .* /
もう 1 文字手放す
/usr/bin/zsh
^ .* /
成功するまで手放す
/usr/bin/zsh
^ .* /
やった ! マッチ成功
/usr/bin/zsh
^ .* /
というわけで、全体として下線部がマッチした
/usr/bin/zsh
ここを空文字に置換すると
/usr/bin/zsh
ディレクトリ部分がなくなる
zsh
繰り返し回数の選び方
● 選択肢が 2 つあったら、まずは長くなる方を試す
● 全体としてマッチに失敗したら、選ばれなかった方を試す
言い方を変えると
● * とか + とか回数指定は欲張り
● 欲張りすぎて全体としてマッチに失敗してしまう場合は文字を手放す
ここまで分かれば微妙な問題でもどこにマッチするか分かる
まとめ
まとめ● 正規表現のメタ文字は
いっぱいある
● 基本的なやつが分かってしまえば、あとは一覧表を見ながら使えば OK
まとめ● * や + は欲張り
● 欲張りすぎてマッチに失敗するときは文字を手放す
ぜひ、正規表現を使ってみてください
ありがとうございました