L'astuce consiste à compter le nombre caractères de guillemets non échappés que vous avez réussi. En supposant que le SQL est syntaxiquement correct, les points-virgules après un nombre pair de caractères de guillemets non échappés seront ceux que vous voulez, et les points-virgules après un nombre impair de caractères guillemets non échappés feront partie d'un littéral de chaîne. (N'oubliez pas que les littéraux de chaîne peuvent contenir des caractères de guillemets correctement échappés.)
Si vous voulez une fiabilité à 100%, vous aurez besoin d'un vrai analyseur SQL, comme this. (Je viens de googlé « analyseur SQL en PHP » Je ne sais pas si cela fonctionne ou non..)
EDIT:
Je ne pense pas qu'il soit possible de trouver des paires de caractères de guillemets sans échappement en utilisant rien mais regex. Peut-être un gourou de la regex me prouvera-t-il que je me trompe, mais il semble juste trop sacrément difficile de faire la distinction entre des guillemets échappés et des caractères de guillemets non échappés dans autant de combinaisons possibles. J'ai essayé des assertions et des backrefs sans succès.
Ce qui suit est pas une solution pure regex, mais je pense que cela fonctionne:
preg_match_all("/(?:([^']*'){2})*[^']*;/U", str_replace("\\'", "\0\1\2", $input), $matches);
$output = array_map(function($str){ return str_replace("\0\1\2", "\\'", $str); }, $matches[0]);
Fondamentalement, nous remplaçons temporairement des guillemets se sont échappés avec une chaîne d'octets qui est extrêmement improbable, dans ce cas \0\1\2
. Après cela, tous les caractères de citation qui restent sont les unsescaped. L'expression régulière sélectionne les points-virgules précédés d'un nombre pair de caractères de citation. Ensuite, nous restaurons les caractères de guillemets échappés. (J'ai utilisé une fermeture ici, donc c'est PHP 5.3 seulement.)
Si vous n'avez pas besoin de traiter les caractères de guillemets à l'intérieur des littéraux de chaîne, oui, vous pouvez facilement le faire avec regex pure.
je dois briser le; mais il y a le problème de l'avoir; citations intérieures. Il est possible d'écrire un petit code pour le faire mais je me demandais si c'était possible en utilisant des expressions régulières. – Rafael
La solution preg_match_all peut vous aider. – ReinaldoNS
ouais !!! preg_match_all est la chose cool! – krico