0

より低い文字列を取得する方法を検索しますが、引用符内のテキストの大文字と小文字を変更しません。

文字列:

SELECT * FROM UtilisateurApplicatif WHERE idUtilisateurApplicatif <> "-1" AND Identification = "TOTO" AND MotDePasse = "TotoTUTU" AND Actif = 1

私が欲しい結果:

select * from utilisateurapplicatif where idutilisateurapplicatif <> "-1" and identification = "TOTO" and motdepasse = "TotoTUTU" and actif = 1
4

1 に答える 1

1

一致結果に関数を適用できるようにする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 回エスケープする必要があります。

于 2013-08-01T00:21:53.157 に答える