【问题标题】:Javascript RegExp replace with negative lookaheadJavascript RegExp 替换为负前瞻
【发布时间】:2010-09-21 14:27:03
【问题描述】:

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

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

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

谢谢

【问题讨论】:

    标签: javascript regex negative-lookahead


    【解决方案1】:

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

    如果需要这样的话,如果你先把它分解成名称/值对,你可能会更容易处理这个查询字符串。

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

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

    【讨论】:

    • 感谢您的回答。对我来说,最简单的解决方案似乎是首先将 & 替换为 %26。然后做我的处理。
    【解决方案2】:

    您根本不需要指定以下&

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

    因为[^&] 已经匹配除& 之外的任何字符。再者,如果category是最后一个参数,连&后面都没有。

    【讨论】:

    • 如果值具有编码 &这就是我认为他试图解决的问题。
    • @adam0101:URI 对 HTML 字符引用一无所知,因为 URI 不是 HTML。 & 分隔名称/值对(请参阅w3.org/TR/html4/interact/forms.html#h-17.13.4.1)。这意味着 category=New&Value&cat2=blah 产生三个名称/值对:category 具有 Newamp;Value 没有值,cat2 具有blah.
    • 可能是这样,但如果他正在使用的查询字符串有与号编码为 &如果可能的话,他将需要可以处理该问题的代码,或者修复查询字符串的创建方式,而不是 %26。
    【解决方案3】:

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

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

    【讨论】:

    • 如果值为 'category=New&Value&cat2=blah' 这将捕获 'category=New&' 而不是 'category=New&Value&' 这正是我认为他想要的。
    【解决方案4】:

    你可以试试:

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

    即使类别前面有?,这也会替换,如/foo.php?category=bar

    【讨论】:

      【解决方案5】:

      /(\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
      

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

      【讨论】:

        【解决方案6】:

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

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

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

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

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

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

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

        这仍然很混乱,并且无法处理 URL 编码的参数名称(即c%61tegory 是表示category 的有效替代方式)或具有相同名称的多个参数。如果你想更健壮,你可以转储正则表达式并进行完整的查询字符串解析/重建。查看this answer 中的函数并执行以下操作:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多