简体   繁体   English

用负前瞻替换Javascript RegExp

[英]Javascript RegExp replace with negative lookahead

I am trying to replace some value in the query string of the current page using JS. 我正在尝试使用JS替换当前页面的查询字符串中的某些值。 Eg: from category=Old Value to category=New Value . 例如:从category=Old Valuecategory=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; 幸运的是,所有“&”号都是URL编码的,所以我知道我应该丢弃该放大器。 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;)]+&?/ 我尝试了此正则表达式,但没有运气: /category=[^&(?!amp;)]+&?/

Thanks 谢谢

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 & . 此外,如果category是最后一个参数,则甚至没有跟随&

Why are ampersands being encoded as & 为什么“&”号被编码为& instead of %26? 而不是%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. 然后,您可以使用每个值,而不必担心它是否包含编码的&。

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 /foo.php?category=bar

You don't get lookbehind in JavaScript regular expressions. 您不会在JavaScript正则表达式中有所顾忌。 You do get lookahead, but it is unreliable in IE, so best avoided unless you really know what you're doing. 确实可以超前,但在IE中不可靠,因此最好避免使用,除非您真的知道自己在做什么。

[^&(?!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 ) . 你不能在使用前瞻[]字符组:你是说这里是匹配字符不&(?!amp;)

However you should not see & 但是,您不应看到& anyway: you should be working on a plain, unencoded query string, eg. 无论如何:您应该使用纯净的,未编码的查询字符串,例如。 as fetched from location.search . location.search获取。 (If you are hacking at HTML markup in a string with regex you've got much, much bigger problems.) (如果您正在使用正则表达式对字符串中的HTML标记进行黑客攻击,则会遇到很多非常大的问题。)

If you are getting the query string from location.search , you'll have a ? 如果你正在从查询字符串location.search ,你就会有一个? 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. 根据HTML4第B.2.2节作为可能的分隔符,并使用encodeURIComponent以便对无效字符(如空格)和特殊字符(如&本身)进行正确的URL编码。 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. 这仍然很混乱,并且不能处理URL编码的参数名称(即c%61tegory是一种有效的替代方式来表示category )或具有相同名称的多个参数。 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);

/(\\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. 您可能要添加全局开关。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM