【JavaScript】正規表現の肯定先(後)読みと否定先(後)読み

  • このエントリーをはてなブックマークに追加

正規表現の肯定先(後)読みと否定先(後)読みは^(先頭)、$(末尾)、\b(単語の境界)同様に「位置へのマッチ」である。
この「位置へのマッチ」はアンカーと呼ばれる。
長さ0の文字列にマッチすると考えて、ゼロ幅アサーション(zero-length assertion)やゼロ幅マッチ(zero-length match)とも呼ばれる。

assertion(名)《コ》アサーション◆プログラムの形式検証における成立条件

肯定先読み(Positive lookahead)
文字列「Java」の先に文字列「Script」が存在する場合に限り、文字列「Java」にマッチする。
つまり、文字列「Java〇〇〇」の場合、「Java」の右側の「〇〇〇」が「Script」の場合に限り、
文字列「Java」にマッチする。

否定先読み(Negative lookahead)
文字列「Java」の先に文字列「Script」が存在しない場合に限り、文字列「Java」にマッチする。
つまり、文字列「Java〇〇〇」の場合、「Java」の右側の「〇〇〇」が「Script」ではない場合に限り
文字列「Java」にマッチする。

肯定後読み(Positive lookbehind)
文字列「Script」の後ろに文字列「Java」が存在する場合に限り、文字列「Script」にマッチする。
つまり、文字列「〇〇〇Script」の場合、「Script」の左側の「〇〇〇」が「Java」の場合に限り、
文字列「Script」にマッチする。

否定後読み(Negative lookbehind)
文字列「Script」の後ろに文字列「Java」が存在しない場合に限り、文字列「Script」にマッチする。
つまり、文字列「〇〇〇Script」の場合、「Script」の左側の「〇〇〇」が「Java」ではない場合に限り、文字列「Script」にマッチする。

※「先読み」の「先」は「このあとに続く部分」という意味で使用している。
『「先読み」の対義語は「後読み」ではないのでは?』という意見がネットにあった。
PHP: 言明 – Manual ExternalLink では「戻り読み」と訳されている。
私は訳さずに「先読み」を「 lookahead」、「後読み」を「lookbehind」と英語で言った方が良いと思う。
「先読み」、「後読み」はまとめて 「lookaround」と呼ばれる。

「肯定先(後)読み」、「否定先(後)読み」は括弧内にマッチしたときに、テキストの操作位置が開始位置に巻き戻されて事実上何もマッチしなことを除けば、非キャプチャーグループと同じになる。
「肯定先(後)読み」、「否定先(後)読み」は位置へのマッチとなる。

肯定先(後)読みと否定先(後)読みの例を次に示す




let regex;

console.log("-----");

console.log("1:肯定先読み/Java(?=Script)/");

regex = /Java(?=Script)/;

console.log("Java:"+regex.test("Java"));
console.log("Script:"+regex.test("Script"));
console.log("JavaScript:"+regex.test("JavaScript"));
console.log("TypeScript:"+regex.test("TypeScript"));
console.log("JavaWorld:"+regex.test("JavaWorld"));

console.log("2:否定先読み/Java(?!Script)/");

regex = /Java(?!Script)/;

console.log("Java:"+regex.test("Java"));
console.log("Script:"+regex.test("Script"));
console.log("JavaScript:"+regex.test("JavaScript"));
console.log("TypeScript:"+regex.test("TypeScript"));
console.log("JavaWorld:"+regex.test("JavaWorld"));

console.log("3:肯定後読み/(?<=Java)Script/");

regex = /(?<=Java)Script/;

console.log("Java:"+regex.test("Java"));
console.log("Script:"+regex.test("Script"));
console.log("JavaScript:"+regex.test("JavaScript"));
console.log("TypeScript:"+regex.test("TypeScript"));
console.log("JavaWorld:"+regex.test("JavaWorld"));

console.log("4:否定後読み/(?<!Java)Script/");

regex = /(?<!Java)Script/;

console.log("Java:"+regex.test("Java"));
console.log("Script:"+regex.test("Script"));
console.log("JavaScript:"+regex.test("JavaScript"));
console.log("TypeScript:"+regex.test("TypeScript"));
console.log("JavaWorld:"+regex.test("JavaWorld"));

console.log("-----");

/*

-----
1:肯定先読み/Java(?=Script)/
Java:false
Script:false
JavaScript:true
TypeScript:false
JavaWorld:false
2:否定先読み/Java(?!Script)/
Java:true
Script:false
JavaScript:false
TypeScript:false
JavaWorld:true
3:肯定後読み/(?<=Java)Script/
Java:false
Script:false
JavaScript:true
TypeScript:false
JavaWorld:false
4:否定後読み/(?<!Java)Script/
Java:false
Script:true
JavaScript:false
TypeScript:true
JavaWorld:false
-----

*/

参考
正規表現の先読み・後読み (zenn.dev) ExternalLink
第58回 正規表現の勘所―わかりづらい記法の覚え方、先読みや後読みの実践(3) | gihyo.jp ExternalLink
先読みと後読み(Lookahead/lookbehind) (javascript.info) ExternalLink

  • このエントリーをはてなブックマークに追加

SNSでもご購読できます。

コメントを残す

*