Question

I'm trying to validate a query with preg_match. I want to replace all %s, %d and %f but NOT with \%s, \%d and \%f. My regex is:

$query = "UPDATE FROM lol SET lol = \%s, asd = %s WHERE lol = %d";
$reg = preg_match("(\%s|\%d|\%f)(?!\\\%s|\\\%d|\\\%f)", $query, $matches);
var_dump($matches); // %s and %d, because \%s can't be matched

I'm trying to not match with \%s, because if you do something like: "WHERE st LIKE %s" (starting with s) it will crash. Then I want to validate it with a regex and after replacing to remove the slashes. I will use the matches %s, %d and %f to replace it like str, int and float, so I want to use just one regex. Can you help me?

Was it helpful?

Solution 2

Zerquix, here's the most compact regex I could think of. It only matches the right ones.

$regex = "~\\\\%(*SKIP)(*F)|%[sdf]~";
$string = "match %s, %d and %f but NOT with \%s, \%d and \%f.";
if(preg_match_all($regex,$string,$m)) print_r($m);

See live demo

OTHER TIPS

(?<!\\)(%s|%d|%f)

Didn't test for PHP tho... Because regular expressions in PHP are strings, you'd need to additionally escape each of the two backslashes, so you should have four of them in your PHP string. There are two levels of escaping you need to think about, PHP string and regexp.

EDIT: tested:

echo preg_replace("/(?<!\\\\)(%s|%d|%f)/", "replaced", "%s \\%s X%d")."\n";
// => replaced \%s Xreplaced

Your code looks for %s, %d, %f not followed by %s, %d or %f (no backslash because the string escaping strips one, leaving \%s etc, which is equivalent to %s as far as regexp is concerned since % does not need to be escaped). My code looks for %s, %d, %f not preceded by \.

EDIT2: for your case,

$query = "UPDATE FROM lol SET lol = \%s, asd = %s WHERE lol = %d";
$reg = preg_replace_callback("/(?<!\\\\)(%s|%d|%f)/", function($m) {
    $repl = Array("%d" => "int", "%s" => "str", "%f" => "float");
    return $repl[$m[1]];
  }, $query);
echo $reg."\n";
// => UPDATE FROM lol SET lol = \%s, asd = str WHERE lol = int

However, looking at what you're doing, you'd probably be wiser to use ADODB or something similar for binding parameters, rather than a homebrew solution.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top