【问题标题】:Create RegExps on the fly using string variables使用字符串变量即时创建正则表达式
【发布时间】:2010-12-06 22:26:49
【问题描述】:

假设我想让以下内容可重复使用:

function replace_foo(target, replacement) {
   return target.replace("string_to_replace",replacement);
}

我可能会这样做:

function replace_foo(target, string_to_replace, replacement) {
   return target.replace(string_to_replace,replacement);
}

使用字符串文字,这很容易。但是,如果我想让正则表达式变得更棘手怎么办?例如,假设我想替换所有 string_to_replace。本能地,我会尝试通过执行以下操作来扩展上述内容:

function replace_foo(target, string_to_replace, replacement) {
   return target.replace(/^string_to_replace/,replacement);
}

这似乎不起作用。我的猜测是它认为string_to_replace 是字符串文字,而不是表示字符串的变量。是否可以使用字符串变量动态创建 JavaScript 正则表达式?如果可能的话,这样的事情会很棒:

function replace_foo(target, string_to_replace, replacement) {
   var regex = "/^" + string_to_replace + "/";
   return target.replace(regex,replacement);
}

【问题讨论】:

    标签: javascript regex


    【解决方案1】:

    new RegExp(string, flags),其中flagsgi。所以

    'GODzilla'.replace( new RegExp('god', 'i'), '' )
    

    评估为

    zilla
    

    【讨论】:

    • 并且在使用这种形式时也省略了/ 正则表达式分隔符。
    【解决方案2】:

    使用字符串文字,这很容易。

    真的没有!该示例仅替换了 first 出现的string_to_replace。更常见的是,您希望替换所有出现的位置,在这种情况下,您必须将字符串转换为全局 (/.../g) 正则表达式。您可以使用 new RegExp 构造函数从字符串中执行此操作:

    new RegExp(string_to_replace, 'g')
    

    这样做的问题是字符串文字中的任何正则表达式特殊字符都会以它们的特殊方式表现,而不是普通字符。你必须用反斜杠转义它们才能解决这个问题。不幸的是,没有内置函数可以为您执行此操作,因此您可以使用以下函数:

    function escapeRegExp(s) {
        return s.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')
    }
    

    还请注意,当您在replace() 中使用正则表达式时,替换字符串现在也有一个特殊字符$。如果您想在替换文本中包含文字 $,也必须对其进行转义!

    function escapeSubstitute(s) {
        return s.replace(/\$/g, '$$$$');
    }
    

    (四个$s,因为它本身就是一个替换字符串——啊!)

    现在您可以使用 RegExp 实现全局字符串替换:

    function replace_foo(target, string_to_replace, replacement) {
        var relit= escapeRegExp(string_to_replace);
        var sub= escapeSubstitute(replacement);
        var re= new RegExp(relit, 'g');
        return target.replace(re, sub);
    }
    

    好痛啊。幸运的是,如果你想要做的只是一个没有正则表达式附加部分的直字符串替换,那么有一种更快的方法:

    s.split(string_to_replace).join(replacement)
    

    ...仅此而已。这是一个通俗易懂的成语。

    说我想替换除 string_to_replace 之外的所有内容

    这是什么意思,你想替换所有不参与匹配字符串的文本片段?用^ 替换当然不是这样,因为^ 表示字符串开始标记,而不是否定。 ^ 只是[] 字符组中的否定。也有负面的前瞻(?!...),但在 JScript 中存在问题,因此您通常应该避免它。

    您可以尝试匹配“所有内容”字符串,并使用函数丢弃匹配字符串之间的任何空白段:

    var re= new RegExp('(.*)($|'+escapeRegExp(string_to_find)+')')
    return target.replace(re, function(match) {
        return match[1]===''? match[2] : replacement+match[2];
    });
    

    同样,拆分可能更简单:

    var parts= target.split(string_to_match);
    for (var i= parts.length; i-->0;)
        if (parts[i]!=='')
            parts[i]= replacement;
    return parts.join(string_to_match);
    

    【讨论】:

      【解决方案3】:

      正如其他人所说,使用new RegExp(pattern, flags) 来执行此操作。值得注意的是,您会将字符串文字传递给此构造函数,因此必须对每个反斜杠进行转义。例如,如果您希望正则表达式与反斜杠匹配,则需要说 new RegExp('\\\\'),而正则表达式文字只需为 /\\/。根据您打算如何使用它,您应该警惕在没有充分预处理(转义特殊字符等)的情况下将用户输入传递给此类函数。如果不这样做,您的用户可能会得到一些非常意外的结果。

      【讨论】:

      • 这个答案虽然不是最详细的,但确实提到了一个我刚刚坚持了一个小时的关键细节:逃避任何特殊序列。例如,我正在搜索以某个词开头的单词,所以我需要的正则表达式是/\b[term]\B/,但在构造它时我需要调用new RegExp("\\b"+ term + "\\B")。微小但重要的区别,并且很难发现,因为直接将它用作正则表达式确实按预期工作。
      【解决方案4】:

      是的,你可以。

      https://developer.mozilla.org/en/JavaScript/Guide/Regular_Expressions

      function replace_foo(target, string_to_replace, replacement) {
         var regex = new RegExp("^" + string_to_replace);
         return target.replace(regex, replacement);
      }
      

      【讨论】:

        【解决方案5】:

        我认为我有一个很好的例子来突出显示字符串中的文本(它发现不是看寄存器而是使用寄存器突出显示)

        function getHighlightedText(basicString, filterString) {
        
            if ((basicString === "") || (basicString === null) || (filterString === "") || (filterString === null)) return basicString;
        
            return basicString.replace(new RegExp(filterString.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\\\$&'), 'gi'),
                function(match)
                    {return "<mark>"+match+"</mark>"});
        
        }
        

        http://jsfiddle.net/cdbzL/1258/

        【讨论】:

          【解决方案6】:

          一个非常简单的解决方案是这样的:

          function replace(target, string_to_replace, replacement) {
            return target.split(string_to_replace).join(replacement);
          }
          

          根本不需要正则表达式

          它似乎也是现代浏览器上最快的https://jsperf.com/replace-vs-split-join-vs-replaceall

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-05-16
            • 2021-07-19
            • 2011-10-27
            • 2013-05-06
            • 2017-06-15
            • 2016-10-22
            相关资源
            最近更新 更多