CBeTJlu4ok
CBeTJlu4ok

Reputation: 1112

Regex match images but not inside img tag

I have a function which converts all external image links into img tags in a string. It works well but also matches links inside <img> tag

for example:

$text = '<p>lorem ipsum http://example.jpg <img src="example.jpg"></p>';
echo make_clickable($text);

function make_clickable($text) {
    $replace = '<p class="update-image"><a href="$0" target="_blank"><img src="$0"></a></p>';
    $text = preg_replace('~https?://[^/\s]+/\S+\.(jpg|png|gif)~i', $replace, $text );
    return $text;
}

this test will match both, plain text and src too. it there a way to exclude img tag?

Upvotes: 1

Views: 1150

Answers (2)

HamZa
HamZa

Reputation: 14921

You may use some non-well-known regex power:

<img[^>]*>(*SKIP)(*FAIL)|https?://[^/\s]+/\S+\.(?:jpg|png|gif)

Let's explain the pattern a bit:

<img                # match a literal <img
[^>]*               # match anything except > zero or more times
>                   # match a literal >
(*SKIP)(*FAIL)      # make it fail
|                   # or
https?              # match http or https
://                 # match a literal ://
[^/\s]+             # match anything except white-space and forward slash one or more times
/                   # match a literal /
\S+                 # match a non-white-space one or more times
\.                  # match a literal dot
(?:jpe?g|png|gif)   # match jpg, jpeg, png, gif
                    # Don't forget to set the i modifier :)

The idea is to match the img tag and skip it, meanwhile match all those URI's.

Online demo

Upvotes: 4

php_nub_qq
php_nub_qq

Reputation: 16017

$replace = '<p class="update-image"><a href="$1" target="_blank"><img src="$1"></a></p>';
$text = preg_replace('~(https?://[^/\s]+/\S+\.(jpg|png|gif))(?:\s|$|\n)~i', $replace, $text );

EDIT: Your regex doesn't seem to match anything in my tests, but what I've added at the end is (?:\s|$|\n). I hope you get the point.

Upvotes: 1

Related Questions