Thursday, January 27, 2011

Replacing the nth instance of a regex match in Javascript

I'm trying to write a regex function that will identify and replace a single instance of a match within a string without affecting the other instances. For example, I have this string:

12||34||56

I want to replace the second set of pipes with ampersands to get this string:

12||34&&56

The regex function needs to be able to handle x amount of pipes and allow me to replace the nth set of pipes, so I could use the same function to make these replacements:

23||45||45||56||67 -> 23&&45||45||56||67

23||34||98||87 -> 23||34||98&&87

I know that I could just split/replace/concat the string at the pipes, and I also know that I can match on /\|\|/ and iterate through the resulting array, but I'm interested to know if it's possible to write a single expression that can do this. Note that this would be for Javascript, so it's possible to generate a regex at runtime using eval(), but it's not possible to use any Perl-specific regex instructions.

  • here's something that works:

    "23||45||45||56||67".replace(/^((?:[0-9]+\|\|){n})([0-9]+)\|\|/,"$1$2&&")
    

    where n is the one less than the nth pipe, (of course you don't need that first subexpression if n = 0)

    And if you'd like a function to do this:

    function pipe_replace(str,n) {
       var RE = new RegExp("^((?:[0-9]+\\|\\|){" + (n-1) + "})([0-9]+)\|\|");
       return str.replace(RE,"$1$2&&");
    }
    
    From Sam Hasler
  • function pipe_replace(str,n) { m = 0; return str.replace(/\|\|/g,function (x){ n++; if (n==m){return "&&"} else {return x} }); }

0 comments:

Post a Comment