I’m using an application to search this website that I don’t have control of right this moment and was wondering if there is a way to ignore duplicate matches using only regex.
Right now I wrote this to get matches for the image source in the pages source code
uses this to retrieve srcs
<span> <img id="imgProduct.*? src="/(.*?)" alt="
from this
<span> <img id="imgProduct_1" class="SmPrdImg selected"
onclick="(some javascript);" src="the_src_I_want1.jpg" alt="woohee"> </span>
<span> <img id="imgProduct_2" class="SmPrdImg selected"
onclick="(some javascript);" src="the_src_I_want2.jpg" alt="woohee"> </span>
<span> <img id="imgProduct_3" class="SmPrdImg selected"
onclick="(some javascript);" src="the_src_I_want3.jpg" alt="woohee"> </span>
the only problem is that the exact same code listed above is duplicated way lower in the source. Is there a way to ignore or delete the duplicates using only regex?
Your pattern’s not very good; it’s way too specific to your exact source code as it currently exists. As @Truth commented, if that changes, you’ll break your pattern. I’d recommend something more like this:
That will match the contents of any
srcattribute inside any<img>tag, no matter how much your source code changes.To prevent duplicates with regex, you’ll need lookahead, and this is likely to be very slow. I do not recommend using regex for this. This is just to show that you could, if you had to. The pattern you would need is something like this (I tested this using Notepad++’s regex search, which is based on PCRE and more robust than JavaScript’s, but I’m reasonably sure that JavaScript’s regex parser can handle this).
You’ll then get a match for the last instance of every
src.The Breakdown
For illustration, here’s how the pattern works:
This makes sure that we are inside a
<img>tag whensrccomes up, and then makes sure we match only what is inside the quotes (which can be either single or double quotes; since neither is a legal character in a filename anyway we don’t have to worry about mixing quote types or escaped quotes).The
(?!starts a negative lookahead: we are requiring that the following pattern cannot be matched after this point.Then
(?:.|\s)*matches any character or any whitespace. This is because JavaScript’s.will not match a newline, while\swill. Mostly, I was lazy and didn’t want to write out a pattern for any possible line ending, so I just used\s. The*, of course, means we can have any number of these. That means that the following (still part of the negative lookahead) cannot be found anywhere in the rest of the file. The(?:instead of(means that this parenthetical isn’t going to be remembered for backreferences.That bit is
<img[^>]*src=['"]\1['"]. This is very similar to the initial pattern, but instead of capturing thesrcwith([^'"]*), we’re referencing the previously-capturedsrcwith\1.Thus the pattern is saying "match any
srcin animgthat does not have anyimgwith the samesrcanywhere in the rest of the file," which means you only get the last instance of eachsrcand no duplicates.If you want to remove all instances of any
imgwhosesrcappears more than once, I think you’re out of luck, by the way. JavaScript does not support lookbehind, and the overwhelming majority of regex engines that do wouldn’t allow such a complicated lookbehind anyway.