如何在正则表达式中使用变量?

How do you use a variable in a regular expression?

提问人:JC Grubbs 提问时间:1/30/2009 最后编辑:daaawxJC Grubbs 更新时间:11/18/2023 访问量:1250388

问:

我想在 JavaScript 中创建一个方法,我认为使用正则表达式是最简洁的方法。但是,我无法弄清楚如何将变量传递给正则表达式。我已经可以这样做了,它将替换 的所有实例。String.replaceAll()"B""A"

"ABABAB".replace(/B/g, "A");

但我想做这样的事情:

String.prototype.replaceAll = function(replaceThis, withThis) {
    this.replace(/replaceThis/g, withThis);
};

但显然这只会取代文本......那么如何将这个变量传递给我的正则表达式字符串呢?"replaceThis"

JavaScript 正则表达式

评论

21赞 Benjamin Gruenbaum 6/23/2015
请注意,我们目前正在努力将此功能添加到 JavaScript 中,如果您对此有意见,请加入讨论。
15赞 aderchox 4/7/2022
const re = new RegExp(`${replaceThis}`, 'g'); str.replace(re, withThis);

答:

2373赞 Eric Wendelin 1/30/2009 #1

您可以构造一个新的 RegExp 对象,而不是使用语法:/regex\d/g

var replace = "regex\\d";
var re = new RegExp(replace,"g");

您可以通过这种方式动态创建正则表达式对象。然后你会做:

"mystring1".replace(re, "newstring");

评论

326赞 Jonathan Swinney 11/10/2010
如果需要使用类似 的表达式,请务必转义反斜杠:。/\/word\:\w*$/new RegExp( '\\/word\\:\\w*$' )
54赞 dronus 2/13/2014
该问题表明,正则表达式仅用于执行常量字符串替换。所以这是答案是错误的,因为如果字符串包含正则表达式元字符,它会失败。可悲的是,它被投了这么高的票,会让很多人头疼......
40赞 Goose 6/6/2015
传递变量的示例将使其成为一个很好的答案。读完这篇文章后,我仍然在挣扎。
36赞 tvanfosson 1/30/2009 #2
this.replace( new RegExp( replaceThis, 'g' ), withThis );

评论

2赞 Wick 4/4/2019
我喜欢这个答案,因为它不会产生额外的(和无意义的)变量。
43赞 Paige Ruten 1/30/2009 #3

这:

var txt=new RegExp(pattern,attributes);

等价于此:

var txt=/pattern/attributes;

请参见 http://www.w3schools.com/jsref/jsref_obj_regexp.asp

评论

28赞 vladkras 7/9/2013
是的,但在第一个示例中它用作变量,在第二个示例中用作字符串pattern
275赞 Gracenotes 1/30/2009 #4

正如 Eric Wendelin 所提到的,你可以做这样的事情:

str1 = "pattern"
var re = new RegExp(str1, "g");
"pattern matching .".replace(re, "regex");

这会产生 .但是,如果 str1 为 。你期望结果是 ,用 代替句点,但结果会是......"regex matching ."".""pattern matching regex""regex"

regexregexregexregexregexregexregexregexregexregexregexregexregexregexregexregexregexregex

这是因为,尽管是 String,但在 RegExp 构造函数中,它仍然被解释为正则表达式,表示任何非换行符,即字符串中的每个字符。为此,以下函数可能很有用:"."

 RegExp.quote = function(str) {
     return str.replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
 };

然后你可以做:

str1 = "."
var re = new RegExp(RegExp.quote(str1), "g");
"pattern matching .".replace(re, "regex");

屈服。"pattern matching regex"

评论

5赞 some 1/30/2009
您知道要替换的第一个参数可以是普通字符串,而不必是正则表达式吗?str1 = “.”;alert(“模式匹配 .”.replace(str1, “字符串”));
0赞 Gracenotes 1/31/2009
@some:当然。那是因为上面的例子是微不足道的。例如,当您需要搜索或替换与常规字符串组合的模式时,请执行 str.match(new RegExp(“https?://” + RegExp.escape(myDomainName))。很烦人的是,没有内置转义功能。
5赞 chbrown 12/16/2012
developer.mozilla.org/en-US/docs/JavaScript/Guide/......提供了类似的功能,但它们排除了 ,并包含 。-=!:/
8赞 Lawrence Dol 12/4/2015
正确的术语是“转义”,而不是“引用”。顺便说一句。
1赞 Novice 2/12/2018
会是一个安全的替代品吗?/[^\w\s]/g/([.?*+^$[\]\\(){}|-])/g
3赞 Jason S 1/30/2009 #5

虽然您可以动态创建 RegExp(根据对此问题的其他回答),但我会在一篇类似的帖子中回应我的评论:String.replace() 的功能形式非常有用,在许多情况下减少了对动态创建的 RegExp 对象的需求。(这有点痛苦,因为您必须将 RegExp 构造函数的输入表示为字符串,而不是使用斜杠 /[A-Z]+/ 正则表达式文本格式)

150赞 bobince 2/1/2009 #6

"ABABAB".replace(/B/g, "A");

一如既往:除非必要,否则不要使用正则表达式。对于简单的字符串替换,成语是:

'ABABAB'.split('B').join('A')

那么你就不必担心Gracenotes的回答中提到的引用问题了。

评论

18赞 Mitar 4/10/2013
你有没有测量过这比正则表达式快?
4赞 Krease 4/25/2013
这似乎更可取,尤其是在需要匹配特殊正则表达式字符(如“.'
2赞 6/13/2013
嗯......不拆分也采用正则表达式;如果是这样,不会导致同样的问题吗?无论如何。。。。split().join() 在某些平台上可能较慢,因为它是两个操作,而 .replace() 是一个操作,可以优化。
6赞 bobince 6/13/2013
@PacMan--:两者,可以接受字符串或对象。没有的问题是,当你使用一个字符串时,你只会得到一个替换。splitreplaceRegExpreplacesplit
2赞 Wagner Danda da Silva Filho 2/22/2018
基准测试:jsperf.com/replace-vs-split-join-vs-replaceall/23
10赞 unigogo 2/1/2009 #7
String.prototype.replaceAll = function (replaceThis, withThis) {
   var re = new RegExp(replaceThis,"g"); 
   return this.replace(re, withThis);
};
var aa = "abab54..aba".replaceAll("\\.", "v");

使用此工具进行测试

40赞 Zombo 11/28/2012 #8

对于任何希望将变量与 match 方法一起使用的人,这对我有用:

var alpha = 'fig';
'food fight'.match(alpha + 'ht')[0]; // fight
4赞 scripto 5/8/2013 #9

下面是另一个 replaceAll 实现:

    String.prototype.replaceAll = function (stringToFind, stringToReplace) {
        if ( stringToFind == stringToReplace) return this;
        var temp = this;
        var index = temp.indexOf(stringToFind);
        while (index != -1) {
            temp = temp.replace(stringToFind, stringToReplace);
            index = temp.indexOf(stringToFind);
        }
        return temp;
    };
5赞 Alex Li 6/5/2013 #10

为了满足我在正则表达式中插入变量/别名/函数的需求,这就是我想出的:

oldre = /xx\(""\)/;
function newre(e){
    return RegExp(e.toString().replace(/\//g,"").replace(/xx/g, yy), "g")
};

String.prototype.replaceAll = this.replace(newre(oldre), "withThis");

其中'oldre'是我想插入变量的原始正则表达式, 'xx' 是该变量/别名/函数的占位符, “yy”是实际的变量名称、别名或函数。

评论

0赞 RoberRM 6/26/2020
在尝试了在正则表达式中插入变量的所有解决方案后,您的解决方案是唯一对我有用的解决方案。非常感谢!
4赞 Fareed Alnamrouti 6/13/2013 #11

如果对您不起作用,您可以使用它:$1

var pattern = new RegExp("amman", "i");
"abc Amman efg".replace(pattern, "<b>" + "abc Amman efg".match(pattern)[0] + "</b>");
2赞 Ry- 8/17/2013 #12

您始终可以重复使用:indexOf

String.prototype.replaceAll = function(substring, replacement) {
    var result = '';
    var lastIndex = 0;

    while(true) {
        var index = this.indexOf(substring, lastIndex);
        if(index === -1) break;
        result += this.substring(lastIndex, index) + replacement;
        lastIndex = index + substring.length;
    }

    return result + this.substring(lastIndex);
};

当替换包含匹配项时,这不会进入无限循环。

6赞 MetalGodwin 8/20/2013 #13
String.prototype.replaceAll = function(a, b) {
    return this.replace(new RegExp(a.replace(/([.?*+^$[\]\\(){}|-])/ig, "\\$1"), 'ig'), b)
}

像这样测试它:

var whatever = 'Some [b]random[/b] text in a [b]sentence.[/b]'

console.log(whatever.replaceAll("[", "<").replaceAll("]", ">"))
24赞 Salman A 9/15/2014 #14

您需要动态构建正则表达式,为此,您必须使用带有转义的新 RegExp(string) 构造函数

jQuery UI自动完成小部件中有一个内置函数,称为:$.ui.autocomplete.escapeRegex

它将采用单个字符串参数并转义所有正则表达式字符, 使结果可以安全地传递给 。new RegExp()

如果不使用 jQuery UI,则可以从源代码复制其定义:

function escapeRegex( value ) {
    return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
}

并像这样使用它:

"[z-a][z-a][z-a]".replace(new RegExp(escapeRegex("[z-a]"), "g"), "[a-z]");
//            escapeRegex("[z-a]")       -> "\[z\-a\]"
// new RegExp(escapeRegex("[z-a]"), "g") -> /\[z\-a\]/g
// end result                            -> "[a-z][a-z][a-z]"
5赞 keen 11/26/2014 #15

还有 Steven Penny 答案的 CoffeeScript 版本,因为这是 #2 Google 结果......即使 CoffeeScript 只是删除了很多字符的 JavaScript...;)

baz = "foo"
filter = new RegExp(baz + "d")
"food fight".match(filter)[0] // food

在我的特殊情况下:

robot.name = hubot
filter = new RegExp(robot.name)
if msg.match.input.match(filter)
  console.log "True!"

评论

0赞 keen 8/26/2015
为什么要投反对票?coffeescript -IS- javascript 具有自己的特定语法。
3赞 codepleb 1/31/2020
robot.name=hubot不是 JavaScript。
2赞 Ajit Hogade 10/27/2015 #16

一种实现方法是从要替换的文本字段中获取值,另一种方法是“替换为”文本字段,从变量中的文本字段中获取值并将变量设置为 RegExp 函数以进一步替换。就我而言,我使用的是jQuery,但您也可以仅通过JavaScript来完成。

JavaScript 代码:

  var replace =document.getElementById("replace}"); // getting a value from a text field with I want to replace
  var replace_with = document.getElementById("with"); //Getting the value from another text fields with which I want to replace another string.

  var sRegExInput = new RegExp(replace, "g");
  $("body").children().each(function() {
    $(this).html($(this).html().replace(sRegExInput,replace_with));
  });

此代码位于按钮的 Onclick 事件上,您可以将其放在要调用的函数中。

所以现在你可以在 replace 函数中传递一个变量。

评论

0赞 Ben Taliadoros 10/27/2017
replace_with变量将包含 DOM 元素,而不是值本身
0赞 Peter Mortensen 8/22/2021
链接已损坏:“页面未找到 - Mindfire Solutions。404.看来你迷路了。
0赞 Ajit Hogade 8/24/2021
只需忽略链接,您可以使用答案中给出的代码,它应该可以相应地工作
143赞 JBallin 6/13/2018 #17

如果要获取所有匹配项 (),请不区分大小写 (),并使用边界,使其不是另一个单词 () 中的单词:gi\\b

re = new RegExp(`\\b${replaceThis}\\b`, 'gi');

let inputString = "I'm John, or johnny, but I prefer john.";
let replaceThis = "John";
let re = new RegExp(`\\b${replaceThis}\\b`, 'gi');
console.log(inputString.replace(re, "Jack"));

评论

1赞 sam boosalis 4/8/2020
谢谢!(afaict,你的答案是 Emacs/-style 插值的唯一答案,通过模板字符串。rx
0赞 cezar 10/19/2021
怎么样?它会像全球旗帜一样工作吗?replaceAllreplace
1赞 JBallin 10/20/2021
@cezar从技术上讲,您可以使用上面的正则表达式(包括全局标志) - 但这没有任何好处。如果您尝试在没有全局标志的情况下使用它,则会出现错误,请参阅此处replaceAll
1赞 joekevinrayan96 1/18/2022
嗨,我正在尝试使用它,但不起作用'const regex = new RegExp(/(?=.{})。*/g);' 而 digits 是我作为参数传递的数值变量。如果可能的话,你能解释一下我该如何解决这个问题吗?\\b${digits}\\b
0赞 JBallin 9/6/2022
当我用我当前的示例测试它们时,@joekevinrayan96整数工作正常。请创建一个单独的问题,并给出一个最小的可重复示例
3赞 Paul Chris Jones 10/19/2018 #18

这些答案对我来说都不清楚。我最终在如何在 JavaScript 的替换函数中使用变量中找到了一个很好的解释

简单的答案是:

var search_term = new RegExp(search_term, "g");
text = text.replace(search_term, replace_term);

例如:

$("button").click(function() {
  Find_and_replace("Lorem", "Chocolate");
  Find_and_replace("ipsum", "ice-cream");
});

function Find_and_replace(search_term, replace_term) {
  text = $("textbox").html();
  var search_term = new RegExp(search_term, "g");
  text = text.replace(search_term, replace_term);
  $("textbox").html(text);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textbox>
  Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum
</textbox>
<button>Click me</button>

评论

1赞 CyberAP 11/7/2018
您正在覆盖闭包变量,无需在此处使用。另外,如果你通过,否则它会坏掉。var\b\1
0赞 John Shearing 11/24/2019 #19

对于没有正则表达式的多次替换,我采用了以下方法:

      let str = "I am a cat man. I like cats";
      let find = "cat";
      let replace = "dog";


      // Count how many occurrences there are of the string to find 
      // inside the str to be examined.
      let findCount = str.split(find).length - 1;

      let loopCount = 0;

      while (loopCount < findCount) 
      {
        str = str.replace(find, replace);
        loopCount = loopCount + 1;
      }  

      console.log(str);
      // I am a dog man. I like dogs

解决方案的重要部分是在这里找到的

3赞 user8094098 12/17/2019 #20

此自调用函数将使用索引遍历 replacerItems,并在每次传递时全局更改字符串上的 replacerItems[index]。

  const replacerItems = ["a", "b", "c"];    

    function replacer(str, index){
          const item = replacerItems[index];
          const regex = new RegExp(`[${item}]`, "g");
          const newStr = str.replace(regex, "z");
          if (index < replacerItems.length - 1) {
            return replacer(newStr, index + 1);
          }
          return newStr;
    }

// console.log(replacer('abcdefg', 0)) will output 'zzzdefg'
0赞 Victoria Stuart 3/11/2021 #21

作为一个相对的 JavaScript 新手,公认的答案 https://stackoverflow.com/a/494046/1904943 被注意到/赞赏,但它不是很直观。

下面是一个更简单的解释,通过示例(使用简单的 JavaScript IDE)。

myString = 'apple pie, banana loaf';

console.log(myString.replaceAll(/pie/gi, 'PIE'))
// apple PIE, banana loaf

console.log(myString.replaceAll(/\bpie\b/gi, 'PIE'))
// apple PIE, banana loaf

console.log(myString.replaceAll(/pi/gi, 'PIE'))
// apple PIEe, banana loaf

console.log(myString.replaceAll(/\bpi\b/gi, 'PIE'))
// [NO EFFECT] apple pie, banana loaf

const match_word = 'pie';

console.log(myString.replaceAll(/match_word/gi, '**PIE**'))
// [NO EFFECT] apple pie, banana loaf

console.log(myString.replaceAll(/\b`${bmatch_word}`\b/gi, '**PIE**'))
// [NO EFFECT] apple pie, banana loaf

// ----------------------------------------
// ... new RegExp(): be sure to \-escape your backslashes: \b >> \\b ...

const match_term = 'pie';
const match_re = new RegExp(`(\\b${match_term}\\b)`, 'gi')

console.log(myString.replaceAll(match_re, 'PiE'))
// apple PiE, banana loaf

console.log(myString.replace(match_re, '**PIE**'))
// apple **PIE**, banana loaf

console.log(myString.replaceAll(match_re, '**PIE**'))
// apple **PIE**, banana loaf

应用

例如:替换(颜色突出显示)字符串/句子中的单词,[可选]如果搜索词匹配的匹配单词的比例超过用户定义的比例。

注意:保留匹配术语的原始字符大小写。:高亮;: 正则表达式 |正则表达式hlre

mySentence = "Apple, boOk? BOoks; booKEd. BookMark, 'BookmarkeD', bOOkmarks! bookmakinG, Banana; bE, BeEn, beFore."

function replacer(mySentence, hl_term, hl_re) {
    console.log('mySentence [raw]:', mySentence)
    console.log('hl_term:', hl_term, '| hl_term.length:', hl_term.length)
    cutoff = hl_term.length;
    console.log('cutoff:', cutoff)

    // `.match()` conveniently collects multiple matched items
    // (including partial matches) into an [array]
    const hl_terms  = mySentence.toLowerCase().match(hl_re, hl_term);
    if (hl_terms == null) {
        console.log('No matches to hl_term "' + hl_term + '"; echoing input string then exiting ...')
        return mySentence;
    }
    console.log('hl_terms:', hl_terms)
    for (let i = 0;  i < hl_terms.length; i++) {
        console.log('----------------------------------------')
        console.log('[' + i + ']:', hl_terms[i], '| length:', hl_terms[i].length, '| parseInt(0.7(length)):', parseInt(0.7*hl_terms[i].length))
        // TEST: if (hl_terms[i].length >= cutoff*10) {
        if (cutoff >= parseInt(0.7 * hl_terms[i].length)) {
            var match_term = hl_terms[i].toString();

            console.log('matched term:', match_term, '[cutoff length:', cutoff, '| 0.7(matched term length):', parseInt(0.7 * hl_terms[i].length))

            const match_re = new RegExp(`(\\b${match_term}\\b)`, 'gi')

            mySentence = mySentence.replaceAll(match_re, '<font style="background:#ffe74e">$1</font>');
        }
        else {
            var match_term = hl_terms[i].toString();
            console.log('NO match:', match_term, '[cutoff length:', cutoff, '| 0.7(matched term length):', parseInt(0.7 * hl_terms[i].length))
        }
    }
    return mySentence;
}

// TESTS:
// const hl_term = 'be';
// const hl_term = 'bee';
// const hl_term = 'before';
// const hl_term = 'book';
const hl_term = 'bookma';
// const hl_term = 'Leibniz';

// This regex matches from start of word:
const hl_re = new RegExp(`(\\b${hl_term}[A-z]*)\\b`, 'gi')

mySentence = replacer(mySentence, hl_term, hl_re);
console.log('mySentence [processed]:', mySentence)

输出

mySentence [raw]: Apple, boOk? BOoks; booKEd. BookMark, 'BookmarkeD',
bOOkmarks! bookmakinG, Banana; bE, BeEn, beFore.

hl_term: bookma | hl_term.length: 6
cutoff: 6
hl_terms: Array(4) [ "bookmark", "bookmarked", "bookmarks", "bookmaking" ]

----------------------------------------
[0]: bookmark | length: 8 | parseInt(0.7(length)): 5
matched term: bookmark [cutoff length: 6 | 0.7(matched term length): 5
----------------------------------------
[1]: bookmarked | length: 10 | parseInt(0.7(length)): 7
NO match: bookmarked [cutoff length: 6 | 0.7(matched term length): 7
----------------------------------------
[2]: bookmarks | length: 9 | parseInt(0.7(length)): 6
matched term: bookmarks [cutoff length: 6 | 0.7(matched term length): 6
----------------------------------------
[3]: bookmaking | length: 10 | parseInt(0.7(length)): 7
NO match: bookmaking [cutoff length: 6 | 0.7(matched term length): 7

mySentence [processed]: Apple, boOk? BOoks; booKEd.
<font style="background:#ffe74e">BookMark</font>, 'BookmarkeD',
<font style="background:#ffe74e">bOOkmarks</font>! bookmakinG,
Banana; bE, BeEn, beFore.
0赞 Ste 3/21/2021 #22

如果使用正确的语法传递变量,则可以使用下面的代码来执行此操作。

这具有在同一变量中使用标志的额外好处。

此外,当涉及到 等时,您不必在正则表达式中进行双重转义。\\w

var str = 'regexVariable example: This is my example of RegExp replacing with a regexVariable.'
var reVar = /(.*?)(regex\w+?iable)(.+?)/gi;
var resStr = str.replace(new RegExp(reVar), '$1 :) :) :) $2 :) :) :)$3');
console.log(resStr);

// Returns:
// :) :) :) regexVariable :) :) :) example: This is my example of RegExp replacing with a  :) :) :) regexVariable :) :) :).

根据 OP 示例的原型版本:

var str = 'regexVariable prototype: This is my example of RegExp replacing with a regexVariable.'

String.prototype.regexVariable = function(reFind, reReplace) {
return str.replace(new RegExp(reFind), reReplace);
}

var reVar = /(.*?)(regex\w+?iable)(.+?)/gi;

console.log(str.regexVariable(reVar, '$1 :) :) :) $2 :) :) :)$3'));

// Returns:
// :) :) :) regexVariable :) :) :) prototype: This is my example of replacing with a  :) :) :) regexVariable :) :) :).

7赞 user7396942 3/23/2021 #23

您可以将字符串用作正则表达式。不要忘记使用新的正则表达式

例:

var yourFunction = new RegExp(
        '^-?\\d+(?:\\.\\d{0,' + yourVar + '})?'
      )
1赞 LeulAria 8/1/2022 #24

示例:正则表达式开头为

function startWith(char, value) {
    return new RegExp(`^[${char}]`, 'gi').test(value);
}
3赞 Игор Ташевски 8/15/2022 #25

我在这里和stackoverflow或类似论坛上的其他开放票证中找到了很多带有奇怪例子的答案。

在我看来,这是最简单的选择,如何将变量作为模板文字字符串;

const someString = "abc";
const regex = new RegExp(`^ someregex ${someString} someregex $`);

正如你所看到的,我没有在开头或结尾提出斜杠,RegExp 构造函数将重新构造有效的正则表达式文本。也适用于 yup 匹配功能。

评论

0赞 john k 2/16/2023
您没有使用斜杠,而是使用反引号?也许你可以解释这一点。
-1赞 kaptcha 8/25/2022 #26

所有这些答案似乎都非常复杂,而有一个更简单的答案仍然可以使用正则表达式完成工作。

String.prototype.replaceAll = function(replaceThis, withThis) {
    const expr = `${replaceThis}`
    this.replace(new RegExp(expr, "g"), withThis);
};

解释

构造函数接受 2 个参数:表达式和标志。通过在表达式中使用模板字符串,我们可以将变量传入类中,它会将其转换为 .RegExp/(value of the replaceThis variable)/g

0赞 Adam Grant 2/17/2023 #27

如果其他人正在寻找这个,以下是您保留操作员的方法:

// BAD
let foo = "foo"
new RegExp(`${foo}\s`, "g");
// => /foos/g

// GOOD
let foo = "foo"
new RegExp(`${foo}${/\s/.source}`, "g");
// => /foo\s/g
1赞 Maxim Secret 11/18/2023 #28

简单的方法:

String.prototype.replaceAll = function(replaceThis, withThis) {
    const regexp = new RegExp(`${replaceThis}`, 'g');
    this.replace(regexp, withThis);
};