/* * Given a raw regex in a string (and, optionally, a pattern-modifiers string), return a string suitable * for use as a preg pattern. The regex is wrapped in delimiters, with the modifiers (if any) appended. */ function preg_regex_to_pattern($raw_regex, $modifiers = "") { /* * To convert a regex to a pattern, we must wrap the pattern in delimiters (we'll use a pair of * forward slashes) and append the modifiers. We must also be sure to escape any unescaped * occurrences of the delimiter within the regex, and to escape a regex-ending escape * (which, if left alone, would end up escaping the delimiter we append). * * We can't just blindly escape embedded delimiters, because it would break a regex containing * an already-escaped delimiter. For example, if the regex is '\/', a blind escape results * in '\\/' which would not work when eventually wrapped with delimiters: '/\\//'. * * Rather, we'll break down the regex into sections: escaped characters, unescaped forward * slashes (which we'll need to escape), and everything else. As a special case, we also look out * for, and escape, a regex-ending escape. */ if (! preg_match('{\\\\(?:/|$)}', $raw_regex)) /* '/' followed by '\' or EOS */ { /* There are no already-escaped forward slashes, and no escape at the end, so it's * safe to blindly escape forward slashes. */ $cooked = preg_replace('!/!', '\/', $raw_regex); } else { /* This is the pattern we'll use to parse $raw_regex. * The two parts whose matches we'll need to escape are within capturing parens. */ $pattern = '{ [^\\\\/]+ | \\\\. | ( / | \\\\$ ) }sx'; /* Our callback function is called upon each successful match of $pattern in $raw-regex. * If $matches[1] is not empty, we return an escaped version of it. * Otherwise, we simply return what was matched unmodified. */ $f = create_function('$matches', ' // This long if (empty($matches[1])) // singlequoted return $matches[0]; // string becomes else // our function return "\\\\" . $matches[1]; // code. '); /* Actually apply $pattern to $raw_regex, yielding $cooked */ $cooked = preg_replace_callback($pattern, $f, $raw_regex); } /* $cooked is now safe to wrap -- do so, append the modifiers, and return */ return "/$cooked/$modifiers"; } ----------------------------------------------------------------------------- Copyright 1997-2024 Jeffrey Friedl