开发者

Javascript RegExp replace with negative lookahead

开发者 https://www.devze.com 2023-01-16 20:39 出处:网络
I am trying to replace some value in the query string of the current page using JS. Eg: from开发者_如何转开发 category=Old Value to category=New Value.

I am trying to replace some value in the query string of the current page using JS. Eg: from开发者_如何转开发 category=Old Value to category=New Value. To code looks like this:

var sNewValue = 'New Value';
sQueryString = sQueryString.replace(/category=[^&]+&?/, 'category=' + sNewValue);

It works fine except for values that have ampersands. Luckily all the ampersands are URL encoded, so I know I should discard the amp; before the &. I think I should use lookaheads, but I don't know how. I tried this regular expression, but with no luck: /category=[^&(?!amp;)]+&?/

Thanks


Why are ampersands being encoded as & instead of %26? Or am I reading your question wrong?

If that's the way it needs to be, it might be easier for you to deal with this query string if you break it into name/value pairs first.

var pairStrings = sQueryString.split(/&(?!amp;)/gi);

Then you can work with each value without worrying if it contains an encoded & or not.


You don’t need to specify a following & at all:

var sNewValue = 'New Value';
sQueryString = sQueryString.replace(/(^|&)category=[^&]*/, '$1category=' + encodeURIComponent(sNewValue));

Because [^&] does already match any character except &. Furthermore, if category is the last parameter, there even is no following &.


OK, I think I actually found what you need.

var sNewValue = 'category=New Value&';
sQueryString = sQueryString.replace(/category=([^&]|&)*&/, sNewValue)


You can try:

var sNewValue = 'New Value';
sQueryString = sQueryString.replace(/\bcategory=[^&]*/, 'category=' + sNewValue);

This will replace even if category is preceded by ? as in /foo.php?category=bar


/(\bcategory=)(([^&]|&amp\;)*)/

This includes the many different scenarios:

   var s1 = 'http://www.foobar.com/?category=old&foo=bar';
   var s2 = 'http://www.foobar.com/?category=old';
   var s3 = 'http://www.foobar.com/?foo=bar&category=old';
   var s4 = 'http://www.foobar.com/?foo=bar&category=old&value';
   var s5 = 'http://www.foobar.com/?foo=bar&category=old&value&bar=foo';

   var n  = 'NewVal';

   console.log( s1.replace(/(\bcategory=)(([^&]|&amp\;)*)/, "$1" + n) );
   console.log( s2.replace(/(\bcategory=)(([^&]|&amp\;)*)/, "$1" + n) );
   console.log( s3.replace(/(\bcategory=)(([^&]|&amp\;)*)/, "$1" + n) );
   console.log( s4.replace(/(\bcategory=)(([^&]|&amp\;)*)/, "$1" + n) );
   console.log( s5.replace(/(\bcategory=)(([^&]|&amp\;)*)/, "$1" + n) );

   // s1 output: http://www.foobar.com/?category=NewVal&foo=bar
   // s2 output: http://www.foobar.com/?category=NewVal
   // s3 output: http://www.foobar.com/?foo=bar&category=NewVal
   // s4 output: http://www.foobar.com/?foo=bar&category=NewVal
   // s5 output: http://www.foobar.com/?foo=bar&category=NewVal&bar=foo

You may want to add a global switch.


You don't get lookbehind in JavaScript regular expressions. You do get lookahead, but it is unreliable in IE, so best avoided unless you really know what you're doing.

[^&(?!amp;)]+&

yeah, this doesn't really make any sense. You can't use lookahead in a [] character group: what you're saying here is match characters that aren't &, (, ?, ! , a, m, p, ;, or ).

However you should not see & anyway: you should be working on a plain, unencoded query string, eg. as fetched from location.search. (If you are hacking at HTML markup in a string with regex you've got much, much bigger problems.)

If you are getting the query string from location.search, you'll have a ? on the front if there's any query. So you can match the beginning with either & or ?, and do your regex match on:

location.search.replace(
    /([?&;]category=)[^&;]+/,
    '$1'+encodeURIComponent(sNewValue)
);

note I have also included ; as a possible separator as per HTML4 section B.2.2, and used encodeURIComponent so that invalid characters like spaces and special characters like & itself get properly URL-encoded. Also the character $, which otherwise has special meaning in a regexp replacement string.

This is still quite messy, and doesn't cope with URL-encoded parameter names (ie c%61tegory is a valid alternative way of saying category) or multiple parameters with the same name. If you want to be more robust about it you could dump the regexps and do full query string parsing/reconstruction. See the functions from this answer and do:

var lookup= queryToLookup(location.search);
lookup['category']= ['New value'];
var query= lookupToQuery(lookup);
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号