$C="[^\\n]";//
return "/(?:{$q}(?:{$C}*?)(?\\\\\\\\)*?{$q}(\s*(?={$q}))?)+/su";
==> /(?:{$q}(?:{$C}*?)(?<!\\\\)(?>\\\\\\\\)*?{$q}(\s*(?={$q}))?)+/su を理解する。
- 最後の /su は、sがマルチライン検索、uはUnicode
- (?:........................)+ は、"abc""def"のように、
"..."が複数つながったケースに適用される。
==> {$q}(?:{$C}*?)(?<!\\\\)(?>\\\\\\\\)*?{$q}
ここで{$q} は、" と仮定する。
==> "(?:{$C}*?)(?<!\\\\)(?>\\\\\\\\)*?"
最初の部分の(?:{$C}*?)は、後で解説するが、ここではストリングをキャプチャーすると理解しておく。
Lazy Mode < *? >なので、この後に続く部分の条件が満たせば、すぐに先へ進む。
==> (?>\\\\\\\\)*?
終わりの部分の (?>\\\\\\\\)*?" を説明する。
八個の\は、PHPのエスケープと、RegExのエスケープを考慮にいれると、\\ になる。
これが取りうる値は、以下のようになる。
----------------------
"
\\"
\\\\"
\\\\\\"
----------------------
==> (?<!\\\\)
(?<!\\\\)の部分は、Negative Lookbehindで、
4個の\は、PHPのエスケープと、RegExのエスケープを考慮にいれると、\ になる。
つまり、\ が前に来てはいけないということである。
(?>\\\\\\\\)*?" と合わせて考えると、以下のような組み合わせは不可となる。
----------------------
\"
\\\"
\\\\\"
\\\\\\\"
----------------------
これらのように、奇数の\ と ” に組み合わせがある場合は、最初の部分の(?:.*?)から
先にでることはできない。
従って、このRegExを最後まで満たすには、以下のような形でおわらなければならない。
----------------------
"
\\"
\\\\"
\\\\\\"
----------------------
==> (?:(?:[^\\n]*?)((?<=\\\\)\\n)?)
これは10kのストリングを処理できなかったのでボツだが、説明しておく。
(?:[^\\n]*?)は、改行以外の文字の連続体。
その後ろにオプションとして、「\を前に持つ改行」がくる。
NO.6をfalseにできるRegExだが、残念にも、
10kのストリングを処理できなかった。
=> (\s*(?={$q}))?
!!!YOU DON'T NEED THIS FEATURE!!!
このRegExは "abc" "def" のような2つのストリングの中間をつなぐ
ホワイトスペースとマッチする。
\s* はホワイトスペースの連続とマッチする。
\s*(?={$q}) は、そのホワイトスペース連続体の後にが$q( ' " )がなければならない。
( ' や " はマッチに含まれない。)
(\s*(?={$q}))? の最後の?は、上記の連続体がなくてもよいが、あるならばマッチする。