Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

negative lookbehind and greedy quantifiers in php

I'm using a regex to find any URLs and link them accordingly. However, I do not want to linkify any URLs that are already linked so I'm using lookbehind to see if the URL has an href before it. This fails though because variable length quantifiers aren't allowed in lookahead and lookbehind for PHP.

Here's the regex for the match:

/\b(?<!href\s*=\s*[\'\"])((?:http:\/\/|www\.)\S*?)(?=\s|$)/i

What's the best way around this problem?

EDIT:

I have yet to test it, but I think the trick to doing it in a single regex is using conditional expressions within the regex, which is supported by PCRE. It would look something like this:

/(href\s*=\s*[\'\"])?(?(1)^|)((?:http:\/\/|www\.)\w[\w\d\.\/]*)(?=\s|$)/i

The key point is that if the href is captured, the match is immediately thrown out due to the conditional (?(1)^|), which is guaranteed to not match. There's probably something wrong with it. I'll test it out tomorrow.

like image 768
Sean Nilan Avatar asked Nov 06 '22 07:11

Sean Nilan


1 Answers

I tried doing the same thing the other way round: ensure that the URL doesn't end in ">:

/((?:http:\/\/|www\.)(?:[^"\s]|"[^>]|(*FAIL))*?)(?=\s|$)/i

But for me that looks pretty hacky, I'm sure you can do better.

My second approach is more similar to yours (and thus is more precise):

/href\s*=\s*"[^"]*"(*SKIP)(*FAIL)|((?:http:\/\/|www\.)\S*?)(?=\s|$)/i

If I find an href= I (*SKIP)(*FAIL). This means that I jump to the position the regex engine is at, when it encounters the (*SKIP).

But that's no less hacky and I'm sure there is a better alternative.

like image 130
NikiC Avatar answered Nov 09 '22 03:11

NikiC