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

Posted

技术标签:

【中文标题】如何在正则表达式中使用变量?【英文标题】:How do you use a variable in a regular expression? 【发布时间】:2021-12-05 22:29:20 【问题描述】:

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

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

但我想做这样的事情:

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

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

【问题讨论】:

请注意,我们目前是working on adding this functionality to JavaScript,如果您对此有任何意见,请加入讨论。 【参考方案1】:

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

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

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

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

【讨论】:

如果您需要使用/\/word\:\w*$/ 之类的表达式,请务必转义您的反斜杠:new RegExp( '\\/word\\:\\w*$' ) @gravityboy 你可以做 ('' + myNumber).replace(/10/g, 'a') 或者如果你想要十六进制数字,你可以做 parseInt('' + myNumber, 16)从十进制转换为十六进制。 问题表明 RegEx 仅用于进行常量字符串替换。所以这是错误的答案,因为如果字符串包含 RegEx 元字符,它将失败。可惜票数这么高,会让人头疼…… 一个传递变量的例子会让这个成为一个很好的答案。看完这篇我还在苦苦挣扎。 @JonathanSwinney: / 如果您从字符串构造正则表达式,则没有特殊含义,因此您不需要转义它。 /\/word\:\w*$/ 应该是 new RegExp('/word\\:\\w*$')【参考方案2】:

正如 Eric Wendelin 所说,您可以这样做:

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

这会产生"regex matching ."。但是,如果 str1 是 ".",它将失败。您希望结果是 "pattern matching regex",将句点替换为 "regex",但结果会是......

regexregexregexregexregexregexregexregexregexregexregexregexregexregexregexregexregexregex

这是因为,尽管"." 是一个字符串,但在 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"

【讨论】:

你知道要替换的第一个参数可以是普通字符串,不必是正则表达式? str1 = "."; alert("模式匹配.".replace(str1, "string")); @some:当然。那是因为上面的例子是微不足道的。当您需要搜索或替换与常规字符串组合的模式时,请执行 str.match(new RegExp("https?://" + RegExp.escape(myDomainName)) ,例如。转义函数很烦人不是内置的。 (续)另外,显然 JC Grubbs 需要全局替换;对于大输入,使用 String.replace(String, String) 实现全局替换可能会很慢。我只是说,前两个解决方案有问题,并且在某些输入上会意外失败。 developer.mozilla.org/en-US/docs/JavaScript/Guide/… 提供了类似的功能,但它们排除了-,并包含了=!:/ 正确的术语是“escape”,而不是“quote”。顺便说一句。【参考方案3】:

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

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

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

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

【讨论】:

你有没有测量过这比正则表达式更快? 这似乎更可取,尤其是在需要匹配特殊的正则表达式字符(如“.”)时 嗯...不拆分也需要RegExp;如果是这样,它不会导致同样的问题吗?无论如何... .split().join() 在某些平台上可能会更慢,因为它是两个操作,而 .replace() 是一个操作并且可能会被优化。 @PacMan--:splitreplace 都可以采用字符串或 RegExp 对象。 replacesplit 没有的问题是,当你使用一个字符串时,你只能得到一个替换。 此处为基准:jsperf.com/replace-vs-split-join-vs-replaceall/23【参考方案4】:

如果您想要所有次出现 (g),请不区分大小写 (i),并使用边界以使其不是另一个单词中的单词 (\\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")); // I'm Jack, or johnny, but I prefer Jack.

【讨论】:

谢谢! (afaict,你的答案是 Emacs/rx-style 插值,通过模板字符串明确的唯一答案。) replaceAll 怎么样?它会和带有 global 标志的replace 一样工作吗? @cezar 从技术上讲,您可以将replaceAll 与上面的正则表达式(包括全局标志)一起使用 - 但它没有任何好处。如果您尝试在没有全局标志的情况下使用它,则会收到错误消息,请参阅this。 嗨,我正在尝试使用它但无法正常工作'const regex = new RegExp(/(?=.\\b$digits\\b).*/g);'而数字是我作为参数传递的数字变量。如果可能的话,你能解释一下我该如何解决这个问题吗?【参考方案5】:

这个:

var txt=new RegExp(pattern,attributes);

等价于:

var txt=/pattern/attributes;

见http://www.w3schools.com/jsref/jsref_obj_regexp.asp。

【讨论】:

是的,但在第一个示例中,它使用pattern 作为变量,在第二个示例中作为字符串【参考方案6】:

对于希望通过 ma​​tch 方法使用变量的任何人,这对我有用:

var alpha = 'fig';
'food fight'.match(alpha + 'ht')[0]; // fight

【讨论】:

【参考方案7】:
this.replace( new RegExp( replaceThis, 'g' ), withThis );

【讨论】:

我喜欢这个答案,因为它不会创建额外的(和毫无意义的)变量。【参考方案8】:

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

jQuery UI autocomplete widget 中有一个内置函数,叫做$.ui.autocomplete.escapeRegex

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

如果你没有使用 jQuery UI,你可以复制它的定义from the source:

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]"

【讨论】:

【参考方案9】:
String.prototype.replaceAll = function (replaceThis, withThis) 
   var re = new RegExp(replaceThis,"g"); 
   return this.replace(re, withThis);
;
var aa = "abab54..aba".replaceAll("\\.", "v");

用这个tool测试

【讨论】:

【参考方案10】:
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("]", ">"))

【讨论】:

【参考方案11】:

还有Steven Penny's answer 的 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!"

【讨论】:

为什么要投反对票? coffeescript -IS- 具有自己特定语法的javascript。 robot.name=hubot 不是 javascript。【参考方案12】:

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

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' 是实际的变量名、别名或函数。

【讨论】:

在尝试了在正则表达式中插入变量的每一种解决方案之后,您的解决方案是唯一对我有用的解决方案。非常感谢!【参考方案13】:

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

例子:

var yourFunction = new RegExp(
        '^-?\\d+(?:\\.\\d0,' + yourVar + ')?'
      )

【讨论】:

【参考方案14】:

这是另一个 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;
    ;

【讨论】:

【参考方案15】:

如果$1 不适合你,你可以使用它:

var pattern = new RegExp("amman", "i");
"abc Amman efg".replace(pattern, "<b>" + "abc Amman efg".match(pattern)[0] + "</b>");

【讨论】:

【参考方案16】:

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

【讨论】:

【参考方案17】:

此自调用函数将使用索引遍历 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'

【讨论】:

【参考方案18】:

这些答案对我来说都不是很清楚。我最终在 How to use a variable in replace function of 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>

【讨论】:

你覆盖了一个闭包变量,这里不需要使用var。此外,如果您通过\b\1,它会中断。【参考方案19】:

您的解决方案在这里:

Pass a variable to regular expression

我实现的方法是从文本字段中获取值,该文本字段是您要替换的文本字段,另一个是“替换为”文本字段,从变量中的文本字段中获取值并设置变量到 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_with 变量将包含 DOM 元素而不是值本身 链接已损坏:“找不到页面 - Mindfire 解决方案。404。看起来你迷路了。” 忽略链接,您可以使用答案中给出的代码,它应该可以相应地工作【参考方案20】:

您始终可以反复使用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);
;

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

【讨论】:

【参考方案21】:

对于没有正则表达式的多个替换,我使用了以下内容:

      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

The important part of the solution was found here

【讨论】:

【参考方案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 :) :) :).

【讨论】:

【参考方案23】:

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

这是一个更简单的解释,例如(使用simple 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

应用程序

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

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

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.

【讨论】:

以上是关于如何在正则表达式中使用变量?的主要内容,如果未能解决你的问题,请参考以下文章

在java下如何在正则表达式中添加变量

如何在 python 中使用变量作为正则表达式? [复制]

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

如何在 C++ 的正则表达式中使用变量? [关闭]

如何使用正则表达式在字符串表达式中查找以@开头的变量名?

python中的正则表达式:如何在模式中使用变量字符串? [复制]