取説 正規表現

nanto_vi, 2008-07-19

自己紹介

目次

  1. よくある間違い
  2. 正規表現オブジェクトのメソッド
  3. グローバルマッチ
  4. 文字列のメソッド
  5. まとめ

よくある書き方

var str = "OSC Kansai 2008";
var year = 0;
if (str.match(/(\d+)/)) {
  year = Number(RegExp.$1);
}

何がよくないか

if (str.match(/(\d+)/)) {
  doOtherThing();
  year = Number(RegExp.$1);
}

function doOtherThing() {
  "Firefox 3 is released".match(/(\d+)/);
}

RegExp オブジェクトのメソッド

exec(str)
成功すると配列、失敗すると null を返す
test(str)
成功すると true、失敗すると false を返す

exec メソッド

var array = /bar (\d+)/.exec("foo bar 42");

array[0];    // => "bar 42"
array[1];    // => "42"
array.index; // => 4
array.input; // => "foo bar 42"

安全な書き方

if (str.match(/.../)) {
  var x = RegExp.$1;
  var y = RegExp.lastMatch;
  var z = RegExp.leftContext;
}

var match;
if ((match = /.../.exec(str))) {
  var x = match[1];
  var y = match[0];
  var z = match.input.substring(0, match.index);
}

グローバルマッチ

lastIndex プロパティ
この位置から検索開始
マッチが成功するとマッチ終了位置に更新
マッチが失敗すると 0 にリセット
var re = /\w/g;
var re = new RegExp("\\w", "g");
var str = "a b c";

re.lastIndex; // => 0

re.exec(str); // => ["a"]
re.lastIndex; // => 1

re.exec(str); // => ["b"]
re.lastIndex; // => 3

re.lastIndex = 0;
re.exec(str); // => ["a"]

グローバルマッチの使用例

var str = "foo:10 bar:20 baz:30";

var re = /(\w+):(\d+)/g;
var match;
while ((match = re.exec(str))) {
  keys.push(match[1]);
  values.push(match[2]);
}

ECMAScript 3、Firefox、Opera では以下も可

var match;
while ((match = /(\w+):(\d+)/g.exec(str))) {
  keys.push(match[1]);
  values.push(match[2]);
}

正規表現オブジェクトの複製

function MyObject() {}
MyObject.prototype.re = /.../g;

MyObject.prototype.re.lastIndex がインスタンス間で共有されてしまう

function MyObject() {
  this.re = new RegExp(this.re);
}
MyObject.prototype.re = /.../g;

文字列の match メソッド

String.prototype.match = function (re) {
  if (re.global) {
    var array = [];
    var match;
    while ((match = re.exec(this)))
      array.push(match[0]);
    return array.length ? array : null;
  }
  return re.exec(this);
};

まとめ

おまけ: ECMAScript 4 の正規表現

var re = /             \
  (?P<number> \p{N}+ ) \
  -                    \
  (?P=number)          \
  /xy;
var array = re.exec("123-12345");
array[0];     // => "123-123"
array[1];     // => "123"
array.number; // => "123"

おまけ 2: ゆの in JavaScript with RegExp

function _() {
  return arguments.callee.caller.caller.arguments;
}

RegExp.prototype.valueOf = function () {
  _()[0] = "OSC Kansai ×2008 ";
  delete this.__proto__.valueOf;
  return true;
};

RegExp.prototype.toString = function () {
  _()[0] += /<\s*(.*?)\s*\\?$/m.exec(this.source)[1];
  return true;
};

function ゆの() {
  return arguments[/\
    X / - / X < 来年も来てくださいね! \
  /];
}

ゆの();