Search code examples
regexvbscriptasp-classicbackslashslash

Regular expression to remove repeated slashes that are after a specific word (VBScript/Classic ASP)


I'm struggling here, trying to figure out how to replace all double slashes that come after a specific word.

Example:

<img alt="" src="/pt/webf//2015//47384_1.JPG" height="235" width="378" />
<div>Don't remove this // or this//</div>

I want the string above to look like this:

<img alt="" src="/pt/webf/2015/47384_1.JPG" height="235" width="378" />
<div>Don't remove this // or this//</div>

Notice the double slashes have been replaced with just one slash in the img tag but left unscathed in the div tag. I only want to replace the double slashes IF they come after the word: pt.

I tried something like this:

(?=pt)((.*?)\/\/)+ 

However, the first thing wrong with it is (?=) does not do pattern backtracking, as far as I'm aware. That is, it'll only look for the first matching pattern. The second thing wrong with it is it doesn't work as I intended it to.

https://regex101.com/r/kC4tA5/1

Or maybe I'm going about this the wrong way, since regular expression support is not expansive in VBScript/Classic ASP and I should try to break up the string and process, instead of trying to do everything in one regular expression???

Any help would be appreciated.

Thank you.


Solution

  • I am interpreting your issue as "Removing repeated slashes in all <img src> attributes."

    As I said in the comments, working with HTML requires a parser. HTML is too complex for regular expressions, all kinds of things can go wrong.

    Luckily, there is a parser available to VBScript: The htmlfile object. It creates a standard DOM from your HTML string. So the solution becomes exactly as described:

    Function FixHtml(htmlString)
        Dim doc, img, slashes
    
        Set slashes = New RegExp
        slashes.Pattern = "/+"
        slashes.Global = True
    
        Set doc = CreateObject("htmlfile")
        doc.Write htmlString
    
        For Each img In doc.getElementsByTagName("IMG")
            img.src = slashes.Replace(img.src, "/")
            img.src = Replace(Replace(img.src, "about:blank", ""), "about:", "")
        Next
    
        FixHtml = doc.body.innerHTML
    End Function
    

    Unfortunately, htmlfile is not the most advanced HTML parser in the world, but rest assured that it will still do way better than any regex.

    There are two minor issues:

    1. I found in my tests that for some reason it insists on prepending the img.src with about: or about:blank. This should not happen, but it does. The second line of Replace() calls gets rid of the unwanted additions.

    2. The .innerHTML will produce tags names in upper case, so <img> becomes <IMG> in the output. Also insignificant line breaks in the HTML source might be removed. This is a minor annoyance, I recommend you don't obsess over it.(*)

    But there are two big plus sides as well:

    1. The DOM puts you in a position where you can work with the input in a structured way. You can put in any number of complex fixes now that would have been impossible to do with regex.
    2. The return value of .innerHTML is sane HTML. It will fix any gross blunder in the input and turn it into something that is well-nested, well-escaped and otherwise well-behaved.

    (*) If you do find yourself obsessing over it, you can use the wisdom from this blog post to create a function that replaces all uppercase tags that come out of .innerHTML with lowercase versions of themselves. This actually is something you can use regex for ("(</?[A-Z]+)", to be exact), because we know that there will be no stray < not belonging to a tag anywhere in the string, because that's .innerHTML's guarantee. While it would be a nice exercise (and it introduces you to the little-known fact that VBScript has function pointers), I would say it's not really worth it.