views:

49

answers:

2

In a text, I would like to replace all occurrences of $word by [$word]($word) (to create a link in Markdown), but only if it is not already in a link. Example:

[$word homepage](http://w00tw00t.org)

should not become

[[$word]($word) homepage](http://w00tw00t.org).

Thus, I need to check whether $word is somewhere between [ and ] and only replace if it's not the case.

Can you think of a preg_replace command for this?

A: 

i think

"~$word(?!.*?])~"

 "~$word(?=[^\[\]]*(\[|$))~"

e.g.

$src = "aa foo [ bbb foo xyz ] cc foo dd";
$word = "foo";
print preg_replace("~$word(?=[^\[\]]*(\[|$))~", "[FOO](bar)", $src);
stereofrog
Nope, that would ignore the first `foo` in: `"aa foo bb [ bbb foo xyz ]"`
Bart Kiers
good call......
stereofrog
+3  A: 

This isn't as simple as you might think. The previous answers would fail in many situations. Here's one that should replace every $word that's not inside [] already:

$text = preg_replace('/\G((?:[^\[]|\[[^\]]*\])*?)('.$word.')/', '$1[$2]($2)', $text)

If $word contains special regexp characters, you might want to preg_quote it.

Example

$text = 'aa foo bb [foo bar](http://example.com) cc foo dd';
$word = 'foo';
$text = preg_replace('/\G((?:[^\[]|\[[^\]]*\])*?)('.$word.')/', '$1[$2]($2)', $text);
echo $text;

Output:

aa [foo](foo) bb [foo bar](http://example.com) cc [foo](foo) dd

reko_t
clever solution, thanks!
blinry
Even if `$word` does not contain special regexp characters, you might want to `preg_quote()` it. Simply because it is The Right Thing to do.
Tomalak