【JavaScript】正規表現で文字を自在に指定する(RegExpオブジェクト)②
はい次いきます
正規表現による検索の基本
RegExpオブジェクトの生成の次は
いよいよ文字列を検索する方法を見ていくことにする
以下は文字列からURL文字列を抽出するためのサンプル
var p = /http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/gi; var str = 'このブログはhttp://micomura.hatenablog.jp/です。'; str += 'ちなみにTwitterはHTTPS://twitter.com/micomuraだったりします。'; var result = str.match(p); for(var i = 0; i < result.length; i++){ document.writeln(result[i]); }
おおーできた!
正規表現で検索するには、String.matchメソッドを利用する
(正確にはRegExp.execメソッドでも可能だがこちらは後述)
vは正規表現パターンにマッチした文字列を配列として返す
ここではforループで得られた配列の内容を順に出力している
正規表現のオプションでマッチング時の挙動を制御する
静企業玄以は「g」「i」「m」という3つのオプションがあり
これらを利用すれば正規表現検索の挙動を制御できる
さっきの例だとオプションを"gi"と設定しているので
「文字列全体」を「大文字/小文字区別なし」で検索している
それぞれのオプションを外してみると
どのように動作が変わるかみてみる
var p = /http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/i; var str = 'このブログはhttp://micomura.hatenablog.jp/です。'; str += 'ちなみにTwitterはHTTPS://twitter.com/micomuraだったりします。'; var result = str.match(p); for(var i = 0; i < result.length; i++){ document.writeln(result[i]); }
http://micomura.hatenablog.jp/
undefined
hatenablog.
/
"g"を外してグローバル検索を無効にしているため
最初に一致した文字列が見つかったところで検索を終了している
この場合、searchメソッドは
「最初に一致した文字列全体とサブマッチ文字列」を配列として返す
サブマッチ文字列とは正規表現パターンの中に
丸カッコで示された部分(サブマッチパターン)に
合致した部分文字列のこと
var p = /http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/i;
ほーなるほど
この場合下記のようなサブマッチパターンに対して
それぞれ文字列が返ってきてるわけですね
- (s)
- undefined
- マッチしている部分がない場合はundefined(または空文字)が返ってくる
- ([\w-]+\.)
- hatenablog.
- 複数回マッチしている場合には最後にマッチしたもののみを保持
- (\/[\w- .\/?%&=]*)
- /
わかりました
それでは今度は"i"を外してみますよ
var p = /http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/g; var str = 'このブログはhttp://micomura.hatenablog.jp/です。'; str += 'ちなみにTwitterはHTTPS://twitter.com/micomuraだったりします。'; var result = str.match(p); for(var i = 0; i < result.length; i++){ document.writeln(result[i]); }
大文字/小文字の違いを無視しない(区別する)ように
設定しているため「http(s)://」は「HTTPS://」にはマッチしない
結果「http://micomura.hatenablog.jp/」だけが返ってくる
うむ、そりゃそうだ、わかりやすい
ややわかりにくいのがmパラメータ(マルチラインモード)
別のサンプルで一つ
var p = /^[0-9]{1,}/g; //文字列先頭にある1文字以上の数値を検索 var str = '101匹ワンちゃん\n7人の小人'; var result = str.match(p); for(var i = 0; i < result.length; i++){ document.writeln(result[i]); }
101
マルチラインモードを無効にしている場合
正規表現パターン「^」は単に文字列の先頭を表すため
先頭の「101」にのみ合致する
これをマルチラインモードを有効にすると
var p = /^[0-9]{1,}/gm; //行頭にある1文字以上の数値を検索 var str = '101匹ワンちゃん\n7人の小人'; var result = str.match(p); for(var i = 0; i < result.length; i++){ document.writeln(result[i]); }
101
7
マルチラインモードを有効にすると「^」は「行頭」を表す
結果改行コード「\n」直後にある「7」にもマッチする
なるほどなーふむふむ
また、これは「$」(文字列末尾)についても同様で
マルチラインモードを有効にした場合
「$」は「行末」を表す、はあく
また「/パターン /オプション」はそれ自体がリテラル表現のため
var result = str.match(/^[0-9]{1,}/gm);
このような記述もすることができる、ふむ
matchメソッドとexecメソッドの挙動の違い
正規表現の文字列検索をするには
- String.matchメソッド
- RegExp.execメソッド
を利用するが
これらのメソッドによって得られる結果は
条件によって異なる場合があるため注意が必要
var p = /http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/gi; var str = 'このブログはhttp://micomura.hatenablog.jp/です。'; str += 'ちなみにTwitterはHTTPS://twitter.com/micomuraだったりします。'; var result = p.exec(str); for(var i = 0; i < result.length; i++){ document.writeln(result[i]); }
http://micomura.hatenablog.jp/
undefined
hatenablog.
/
execメソッドはグローバル検索(gオプション)が
有効か否かに関わらず
一度の実行で一つの結果しか返さない
代わりにマッチ文字列全体とサブマッチ文字列を
配列として返す
execメソッドでグローバル検索をした際と同じ結果を得るためには
RegExpオブジェクトの
- 最後にマッチした文字位置を記憶する機能
- 次回のexecメソッドを実行する際、前回のマッチ位置から検索を再開する
という特性を利用して
var p = /http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/gi; var str = 'このブログはhttp://micomura.hatenablog.jp/です。'; str += 'ちなみにTwitterはHTTPS://twitter.com/micomuraだったりします。'; while((result = p.exec(str)) != null){ document.writeln(result[0]); }
このように記述することで望んだ結果が得られるようになる
execメソッドは次の検索結果がない場合にnullを返す
検索を繰り返し
最終的に検索結果が返ってこなくなると
nullが返ってくるためwhile命令を脱出する
なるほどなーなるほどなー