Javascript RegExp替换为负前瞻

Javascript RegExp替换为负前瞻,javascript,regex,negative-lookahead,Javascript,Regex,Negative Lookahead,我试图用JS替换当前页面查询字符串中的一些值。例如:从category=旧值到category=新值。 编写代码的步骤如下所示: var sNewValue = 'New Value'; sQueryString = sQueryString.replace(/category=[^&]+&?/, 'category=' + sNewValue); 它可以正常工作,但有符号的值除外。幸运的是,所有的符号都是URL编码的,所以我知道我应该放弃amp在和之前。我想我应该用looka

我试图用JS替换当前页面查询字符串中的一些值。例如:从
category=旧值
category=新值
。 编写代码的步骤如下所示:

var sNewValue = 'New Value';
sQueryString = sQueryString.replace(/category=[^&]+&?/, 'category=' + sNewValue);
它可以正常工作,但有符号的值除外。幸运的是,所有的符号都是URL编码的,所以我知道我应该放弃amp之前。我想我应该用lookaheads,但我不知道怎么用。我尝试了这个正则表达式,但没有成功:
/category=[^&(!amp;)]+&?/


谢谢

好的,我想我已经找到你需要的了

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

您根本不需要指定以下
&

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

因为
[^&]
已经匹配了除
&
之外的任何字符。此外,如果category是最后一个参数,那么甚至没有下面的
&

为什么要将安培数编码为&;而不是%26?还是我看错了你的问题

如果需要这样做,那么如果首先将查询字符串分解为名称/值对,您可能会更容易处理该查询字符串

var pairStrings = sQueryString.split(/&(?!amp;)/gi);
然后,您就可以处理每个值,而不用担心它是否包含编码的&值。

您可以尝试:

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

即使category前面加了
,这也会被替换,就像在
/foo.php?category=bar

中一样,您不会在JavaScript正则表达式中看到后面的内容。你确实可以向前看,但在IE中它是不可靠的,所以最好避免,除非你真的知道自己在做什么

[^&(?!amp;)]+&
是的,这没有任何意义。您不能在
[]
字符组中使用前瞻:您在这里说的是匹配不是
&
a
m
p

但是,您不应该看到
&无论如何:您应该处理一个普通的、未编码的查询字符串,例如,从
location.search
获取的字符串。(如果你正在用正则表达式破解字符串中的HTML标记,你会遇到很多更大的问题。)

如果您是从
location.search
获取查询字符串,如果有任何查询,则前面会有一个
。因此,您可以将开头与
&
匹配,并在以下位置执行正则表达式匹配:

location.search.replace(
    /([?&;]category=)[^&;]+/,
    '$1'+encodeURIComponent(sNewValue)
);
注:我还包括
作为可能的分隔符,并使用
encodeURIComponent
,以便对无效字符(如空格)和特殊字符(如
&
本身)进行正确的URL编码。还有字符
$
,它在regexp替换字符串中有特殊含义

这仍然非常混乱,无法处理URL编码的参数名称(即
c%61tegory
是表示
类别
的有效替代方式)或具有相同名称的多个参数。如果您想更加健壮,可以转储regexp并执行完整的查询字符串解析/重构。请参阅和中的函数:

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

这包括许多不同的场景:

   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

您可能需要添加一个全局开关。

如果该值为'category=New&;Value&cat2=blah“这将捕获”category=New&“而不是”category=New&;我认为他想要的是Value&。如果Value有一个编码的&;这就是我认为他试图解决的问题。@adam0101:uri对HTML字符引用一无所知,因为uri不是HTML。
分隔名称/值对(请参阅)。这意味着
category=New&;Value&cat2=blah
产生三个名称/值对:类别有
新的
,amp;值没有值,cat2有
blah
。这可能是,但是如果他正在使用的查询字符串中有编码为&;如果可能的话,他需要的不是%26,而是可以处理该问题的代码,或者修复查询字符串的创建方式。谢谢您的回答。对我来说,似乎最简单的解决办法是首先更换&;与%26。然后做我的处理。
   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