ChatGPT解决这个技术问题 Extra ChatGPT

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

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

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

但我想做这样的事情:

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

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

请注意,如果您对此有任何意见,我们目前是 working on adding this functionality to JavaScript,请加入讨论。
const re = new RegExp(`${replaceThis}`, 'g'); str.replace(re, withThis);

V
Viacheslav Dobromyslov

您可以构造一个新的 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*$')
Q
Qtax

正如 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”。顺便说一句。
L
Liam

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

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

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

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


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

如果您想获得所有次出现 (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 风格的插值,通过模板字符串明确的唯一答案。)
replaceAll 呢?它是否与带有 global 标志的 replace 一样工作?
@cezar 从技术上讲,您可以将 replaceAll 与上面的确切正则表达式(包括全局标志)一起使用 - 但它没有任何好处。如果您尝试在没有全局标志的情况下使用它,则会收到错误,请参阅 this
嗨,我正在尝试使用它但无法正常工作'const regex = new RegExp(/(?=.{\\b${digits}\\b}).*/g);'而数字是我作为参数传递的数字变量。如果可能的话,你能解释一下我该如何解决这个问题吗?
P
Paige Ruten

这个:

var txt=new RegExp(pattern,attributes);

相当于:

var txt=/pattern/attributes;

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


是的,但在第一个示例中,它使用 pattern 作为变量,在第二个示例中作为字符串
P
Peter Mortensen

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

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

M
Mike Samuel
this.replace( new RegExp( replaceThis, 'g' ), withThis );

我喜欢这个答案,因为它不会创建额外的(和毫无意义的)变量。
S
Salman A

您需要动态构建正则表达式,为此您必须使用带有转义的 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]"

u
unigogo
String.prototype.replaceAll = function (replaceThis, withThis) {
   var re = new RegExp(replaceThis,"g"); 
   return this.replace(re, withThis);
};
var aa = "abab54..aba".replaceAll("\\.", "v");

使用此 tool 进行测试


M
MetalGodwin
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("]", ">"))

P
Peter Mortensen

还有 Steven Penny's answer 的 CoffeeScript 版本,因为这是 Google 结果的第 2 位……即使 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。
A
Alex Li

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

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


在尝试了在正则表达式中插入变量的每一个解决方案之后,你的解决方案是唯一对我有用的解决方案。非常感谢你!
P
Peter Mortensen

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

例子:

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

s
scripto

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

P
Peter Mortensen

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

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

C
Community

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


佚名

这个自调用函数将使用索引迭代 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'

P
Peter Mortensen

这些答案对我来说都不清楚。我最终在 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"); });函数 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); $("文本框").html(文本); } Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum


您正在覆盖一个闭包变量,此处无需使用 var。此外,如果您通过 \b\1,它会中断。
a
africola

一种实现方法是从文本字段中获取值,该文本字段是您要替换的文本字段,另一个是“替换为”文本字段,从变量中的文本字段获取值并将变量设置为 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。看起来你迷路了。”
只需忽略您可以使用答案中给出的代码的链接,它应该可以相应地工作
R
Ry-

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

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


J
John Shearing

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

      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


P
Peter Mortensen

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

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

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

var str = 'regexVariable 示例:这是我将 RegExp 替换为 regexVariable 的示例。 var reVar = /(.*?)(regex\w+?iable)(.+?)/gi; var resStr = str.replace(new RegExp(reVar), '$1 :) :) :) $2 :) :) :)$3');控制台.log(resStr); // 返回: // :) :) :) regexVariable :) :) :) 示例:这是我将 RegExp 替换为 :) :) :) regexVariable :) :) :) 的示例。

根据 OP 示例的原型版本:

var str = 'regexVariable 原型:这是我将 RegExp 替换为 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')); // 返回: // :) :) :) regexVariable :) :) :) 原型:这是我用 :) 替换的示例 :) :) regexVariable :) :) :)。


P
Peter Mortensen

作为一个相对的 JavaScript 新手,已注意到/赞赏已接受的答案 https://stackoverflow.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.