0

我正在尝试使用 JS 替换当前页面的查询字符串中的某些值。例如:从category=Old Valuecategory=New Value。代码如下所示:

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

它工作正常,除了带有 & 符号的值。幸运的是,所有的 & 符号都是 URL 编码的,所以我知道我应该丢弃amp;&之前。我想我应该使用前瞻,但我不知道如何。我尝试了这个正则表达式,但没有运气:/category=[^&(?!amp;)]+&?/

谢谢

4

6 回答 6

1

您根本不需要指定以下内容&

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

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

于 2010-09-21T14:37:52.487 回答
1

为什么 & 符号被编码为 & 而不是 %26? 还是我读错了你的问题?

如果这是它需要的方式,那么如果您首先将其分解为名称/值对,则处理此查询字符串可能会更容易。

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

然后,您可以使用每个值而不必担心它是否包含编码的 &。

于 2010-09-21T14:46:52.880 回答
0

好的,我想我确实找到了你需要的东西。

var sNewValue = 'category=New Value&';
sQueryString = sQueryString.replace(/category=([^&]|&)*&/, sNewValue)
于 2010-09-21T14:33:40.203 回答
0

你可以试试:

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

即使类别前面?有如/foo.php?category=bar

于 2010-09-21T15:18:58.053 回答
0

您不会在 JavaScript 正则表达式中进行回溯。你确实得到了前瞻,但它在 IE 中是不可靠的,所以最好避免,除非你真的知道你在做什么。

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

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

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

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

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

请注意,我还;根据 HTML4 第 B.2.2 节将其作为可能的分隔符包含在内,并用于encodeURIComponent使无效字符(如空格和特殊字符(如其&本身)得到正确的 URL 编码)。还有字符$,否则在正则表达式替换字符串中具有特殊含义。

这仍然很混乱,并且无法处理 URL 编码的参数名称(即c%61tegory是一种有效的替代方式category)或具有相同名称的多个参数。如果您想对其更加健壮,您可以转储正则表达式并进行完整的查询字符串解析/重构。请参阅此答案中的功能并执行以下操作:

var lookup= queryToLookup(location.search);
lookup['category']= ['New value'];
var query= lookupToQuery(lookup);
于 2010-09-21T15:22:54.127 回答
0

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

这包括许多不同的场景:

   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

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

于 2010-09-21T15:23:42.220 回答