滅多に必要にならないですし、他人とプログラムを共有する際に相手方の理解の邪魔になりやすいのであまり使うことをおすすめできない機能なのですが比較的珍しい正規表現の機能(正規表現を使えてもこの機能は使えない言語が少なくない)が PHP の正規表現エンジンに入っていたのでそれの紹介です。
\Kは PHP の正規表現のエスケープシーケンスの一つであり、それは次の様に説明されています。
\K を使用すると、マッチの開始位置をリセットできます。 たとえば、パターン foo\Kbar は “foobar” にマッチしますが、 結果は “bar” にマッチしたと報告されます。 \K を使用しても、キャプチャした部分文字列には影響を及ぼしません。 たとえば、パターン (foo)\Kbar が “foobar” にマッチしたときの最初の部分文字列は “foo” です。
ざっくばらんに言うと無印のマッチンググループ(preg_match)の位置を変える機能です。より具体的には次の様に動作します。
<?php /** * abcde に対する前方三文字のマッチ中で\Kをずらして挙動例を示します */ preg_match('/^\K.(.)./', 'abcde', $match); echo $match[0] . ", ". $match[1] . "\n"; // abc, b // 正規表現全体がマッチした内の\K以降の abc が[0]に入り、グループ化した部分にあてはまる b が[1]に入る preg_match('/^.\K(.)./', 'abcde', $match); echo $match[0] . ", ". $match[1] . "\n"; // bc, b // 正規表現全体がマッチした内の\K以降の bc が[0]に入り、グループ化した部分にあてはまる b が[1]に入る preg_match('/^.(.)\K./', 'abcde', $match); echo $match[0] . ", ". $match[1] . "\n"; // c, b // 正規表現全体がマッチした内の\K以降の c が[0]に入り、グループ化した部分にあてはまる b が[1]に入る preg_match('/^.(.).\K/', 'abcde', $match); echo $match[0] . ", ". $match[1] . "\n"; // , b // \K以降には何もないため 空文字列 が[0]に入り、グループ化した部分にあてはまる b が[1]に入る /** * preg_replace で置き換わる範囲は $match[0] と同じです。 * \Kの位置によって置換される文字列の範囲が、 * 正規表現自体によって文字列が置換対象となるかどうかが、 * 定まる例を示します */ echo preg_replace('/abc/', '', 'abcd') . "\n"; // d // abc を空文字列に置き換え echo preg_replace('/a\Kbc/', '', 'abcd') . "\n"; // ad // \K の効果により最初のマッチグル―プが \K から始まる bc になり、bcを空文字列に置き換え echo preg_replace('/E\Kbc/', '', 'abcd') . "\n"; // abcd // Ebc がマッチしないのでそのまま echo preg_replace('/(a)\K(bc)/', 'X$1$1$2$2X', 'abcd') . "\n"; // aXaabcbcXd // 括弧指定のマッチグループに \K は関係ないので、\Kで置き換え範囲の bc を aabcbc に置き換え echo preg_replace('/(a)(bc)/', 'X$1$1$2$2X', 'abcd') . "\n"; // XaabcbcXd // 括弧指定のマッチグループに \K は関係ないので、\K抜きの置き換え範囲の abc を aabcbc に置き換え
よく括弧でマッチングループを指定し、指定したマッチングループにあてはまる部分を参照します。この指定したマッチングループと並んで扱われる範囲によく正規表現にマッチした全体が入っています。この全体の部分を制御する方法の一つが \K です。
console.log('abcde'.match(/.(.)./)) // Array [ "abc", "b" ] // ↑のJavascript の match ならば "abc"がその部分です。