如何在正则表达式中使用变量?
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--:split
和 replace
都可以采用字符串或 RegExp
对象。 replace
有 split
没有的问题是,当你使用一个字符串时,你只能得到一个替换。
此处为基准: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】:
对于希望通过 match 方法使用变量的任何人,这对我有用:
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.
【讨论】:
以上是关于如何在正则表达式中使用变量?的主要内容,如果未能解决你的问题,请参考以下文章