一致結果に関数を適用できるようにするpreg_replace_callbackを使用してこれを行うことができます。
$subject = <<<'LOD'
SELECT * FROM UtilisateurApplicatif
WHERE idUtilisateurApplicatif <> "-1"
AND Identification = "TOTO"
AND MotDePasse = "Toto\"TUTU" AND Actif = 1
LOD;
$pattern = <<<'LOD'
~
(?(DEFINE)
(?<DQuotedContent>
(?> [^"\\]++ | (?:\\{2})++ | \\. )*
)
)
" \g<DQuotedContent> " \K | [A-Z]++
~x
LOD;
$result = preg_replace_callback($pattern,
function ($match) { return strtolower($match[0]); },
$subject);
print_r($result);
パターン説明:
パターンの考え方は、前に引用された部分を照合し、それらを一致結果から削除して、strtolowerを適用しないようにすることです。
最初にDQuotedContent
、可能なすべてのコンテンツを二重引用符で囲んだサブパターン ( )を定義します。
- 二重引用符またはバックスラッシュ以外のすべての文字
[^"\\]
- すべての偶数のバックスラッシュ
(?:\\{2})++
(何もエスケープできません)
- エスケープ文字 (エスケープされた二重引用符は、引用符で囲まれた文字列を閉じることはできません)
パターンの主要部分は簡単に記述できるようになりました。
" \g<DQuotedContent> " # quoted part
\K # reset all that have been matched before
| # OR
[A-Z]++ # uppercase letters
\K
は、引用された部分を一致から削除するため、非常に便利であることに注意してください。したがって、コールバック関数は、 strtolowerを適用するために何が一致したかを知る必要はありません。
注意: 読みやすくするために、nowdoc 構文、define セクション、名前付きサブパターン、およびコメント モード ( ~x
) を使用してパターンを記述しましたが、代わりに同じパターンをよりコンパクトなバージョンで使用できます。
$pattern = '~"(?>[^"\\\]++|(?:\\\{2})++|\\\.)*"\K|[A-Z]++~';
nowdoc 構文とは異なり、バックスラッシュは 2 回エスケープする必要があります。