0

I'm trying to use an array of regular expressions to find and replace within a string in PHP, however I'm getting the error unknown modifier. I'm aware this appears to be a popular issue, however I don't understand how to fix it in my scenario.

Here is my original regex pattern:

{youtube((?!}).)*}

I run the following code against it to escape any characters:

$pattern = '/' . preg_quote($pattern) . '/';

That returns the following:

/\{youtube\(\(\?\!\}\)\.\)\*\}/

However, when I run this pattern through preg_replace I get the following error:

Warning: preg_replace() [function.preg-replace]: Unknown modifier 'y' ...

Any idea what needs to be changed, and at what stage of the code I've show here?

Many thanks

Edit 1

As requested, here is the code I'm using:

$content = "{youtube}omg{/youtube}";
$find = array();
$replace = array();

$find[] = '{youtube((?!}).)*}';
$replace[] = '[embed]http://www.youtube.com/watch?v=';
$find[] = '{/youtube((?!}).)*}';
$replace[] = '[/embed]';

foreach ( $find as $key => $value ) {
    $find[$key] = '/' . preg_quote($value) . '/';
}

echo preg_replace($find, $replace, $content);

Here's a live example

Ben Everard
  • 13,652
  • 14
  • 67
  • 96
  • No, why are you using `preg_quote` anyway. It's meant for literal string parts, but you already have a regex pattern. – mario Mar 13 '13 at 12:53
  • mario, I think they tried isolating the cause that way. The fact that it *still* throws weird errors is interesting in itself. – Joey Mar 13 '13 at 12:54
  • @mario I'm using `preg_quote` to solve an earlier problem... but even without it, I get the same error. – Ben Everard Mar 13 '13 at 12:55
  • 1
    Please post the actual code you are running. Because I don't get that exact error for `preg_match("/\{youtube\(\(\?\!\}\)\.\)\*\}/", "");` either, there's no error at all for the actual pattern and the escaped pattern. – mario Mar 13 '13 at 12:58
  • can you post your preg_replace? – djjjuk Mar 13 '13 at 12:59
  • Please see *edit 1* in the original question – Ben Everard Mar 13 '13 at 13:04
  • 1
    Then it's this after all: [Unknown modifier '/' in ...? what is it?](http://stackoverflow.com/q/3565615) – mario Mar 13 '13 at 13:09
  • Oh ****! Oh no guys, I was thinking it was the very first `{youtube}` pattern, not the second. Sorry for being an idiot, @mario, many thanks! – Ben Everard Mar 13 '13 at 13:09

3 Answers3

1

You should pass delimiter as second parameter for preg_quote like this:

$find[$key] = '/' . preg_quote ($value, '/') . '/';

Otherwise, delimiter will not be quoted and thus will cause problems.

Mikhail Vladimirov
  • 13,572
  • 1
  • 38
  • 40
0

Simply change your Regex delimiter to something that's not used in the pattern, in this example I used @ which works fine.

preg_quote only escapes . \ + * ? [ ^ ] $ ( ) { } = ! < > | : -, so when using a non-escaped character in your pattern, but also as your regex delimiter, it's not going to work as expected. Either change the delimiter as above, or pass it into preg_quote explicitely as part of the preg_quote($str, $delimiter) overload.

$content = "{youtube}omg{/youtube}";
$find = array();
$replace = array();

$find[] = '{youtube((?!}).)*}';
$replace[] = '[embed]http://www.youtube.com/watch?v=';
$find[] = '{/youtube((?!}).)*}';
$replace[] = '[/embed]';

foreach ( $find as $key => $value ) {
    $find[$key] = '@' . preg_quote($value) . '@';
}

echo preg_replace($find, $replace, $content);
Rudi Visser
  • 21,350
  • 5
  • 71
  • 97
  • Hi Rudi, long time no speak... how's things? Thanks for you (and @mario) for pointing this issue out, with `preg_quote` it failed to do the replace, however removing this does now work. – Ben Everard Mar 13 '13 at 13:18
  • 1
    It is not always easy to choose delimiter that is not in the pattern, especially when pattern is calculated at run time. Better way is to use standard delimiter `'/'` and pass it to `preg_quote` as second argument, so `preg_quote` will quote it along with other special characters. See my answer for code example. – Mikhail Vladimirov Mar 13 '13 at 13:51
  • @ilmv - Things are good, how're your things? Should email me and catch up :D – Rudi Visser Mar 13 '13 at 14:05
  • @MikhailVladimirov It's not calculated at runtime, and I also mentioned to use the other overload. – Rudi Visser Mar 13 '13 at 14:05
0

I may be sat in a hospital waiting room away from a computer, but what you're doing seems to have way over complicated the problem.

If I am to understand this correctly, you want to replace some like this:

{youtube something="maybe"}http://...{/youtube}

With:

[embed]http://...[/embed]

No?

If that's the case the solution is as simple as something along the lines of:

preg_replace('#{(/?)youtube[^}]*}#', '[\1embed]', $content);

The important considerations being the preservation of the open/closed-ness of the tags, and wrapping the regex in something that doesn't conflict quite so much with your target string, in this case, hashes.

Steve
  • 5,771
  • 4
  • 34
  • 49
  • preg_replace_all may be necessary to ensure you capture all of the tags rather than only the first. – Steve Mar 13 '13 at 13:28