Javascript 如何仅替换捕获的组?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3954927/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to replace captured groups only?
提问by Nicolas Guillaume
I have HTML code before and after the string:
我在字符串前后都有 HTML 代码:
name="some_text_0_some_text"
I would like to replace the 0
by something like : !NEW_ID!
我想用以下内容替换0
:!NEW_ID!
So i made a simple regex :
所以我做了一个简单的正则表达式:
.*name="\w+(\d+)\w+".*
But i don't see how to replace exclusively the captured block.
但我不知道如何专门替换捕获的块。
Is there a way to replace a captured result like ($1) by some other string ?
有没有办法用其他字符串替换像 ($1) 这样的捕获结果?
The result would be :
结果是:
name="some_text_!NEW_ID!_some_text"
回答by Matthew Flaschen
A solution is to add captures for the preceding and following text:
一种解决方案是为前面和后面的文本添加捕获:
str.replace(/(.*name="\w+)(\d+)(\w+".*)/, "!NEW_ID!")
回答by CertainPerformance
Now that Javascript has lookbehind (as of ES2018), on newer environments, you can avoid groups entirely in situations like these. Rather, lookbehind for what comes before the group you were capturing, and lookahead for comes after, and replace with just!NEW_ID!
:
现在 Javascript 具有后视功能(从ES2018 开始),在较新的环境中,您可以完全避免在此类情况下使用组。相反,回顾后为你捕捉组之前会发生什么,以及超前的来后,并将其替换只是!NEW_ID!
:
const str = 'name="some_text_0_some_text"';
console.log(
str.replace(/(?<=name="\w+)\d+(?=\w+")/, '!NEW_ID!')
);
With this method, the full match is onlythe part that needs to be replaced.
使用这种方法,完全匹配的只是需要更换的部分。
(?<=name="\w+)
- Lookbehind forname"
, followed by word characters (luckily, lookbehinds do not have to be fixed width in Javascript!)\d+
- Match one or more digits - the only part of the pattern not in a lookaround, the only part of the string that will be in the resulting match(?=\w+")
- Lookahead for word characters followed by"
`
(?<=name="\w+)
- Lookbehind forname"
,后跟单词字符(幸运的是,在 Javascript 中,lookbehinds 不必固定宽度!)\d+
- 匹配一个或多个数字 - 模式中唯一不在环视中的部分,字符串中唯一将出现在结果匹配中的部分(?=\w+")
- 前瞻单词字符后跟"
`
Keep in mind that lookbehind is pretty new. It works in modern versions of V8 (including Chrome, Opera, and Node), but not in most other environments, at least not yet. So while you can reliably use lookbehind in Node and in your own browser (if it runs on a modern version of V8), it's not yet sufficiently supported by random clients (like on a public website).
请记住,lookbehind 很新。它适用于现代版本的 V8(包括 Chrome、Opera 和 Node),但不适用于大多数其他环境,至少目前还没有。因此,虽然您可以在 Node 和您自己的浏览器中可靠地使用 Lookbehind(如果它在现代版本的 V8 上运行),但它尚未得到随机客户端的充分支持(例如在公共网站上)。
回答by Emma
With two capturing groups would have been also possible; I would have also included two dashes, as additional left and right boundaries, before and after the digits, and the modified expression would have looked like:
使用两个捕获组也是可能的;我还会在数字之前和之后包含两个破折号,作为额外的左右边界,修改后的表达式看起来像:
(.*name=".+_)\d+(_[^"]+".*)
const regex = /(.*name=".+_)\d+(_[^"]+".*)/g;
const str = `some_data_before name="some_text_0_some_text" and then some_data after`;
const subst = `!NEW_ID!`;
const result = str.replace(regex, subst);
console.log(result);
If you wish to explore/simplify/modify the expression, it's been explained on the top right panel of regex101.com. If you'd like, you can also watch in this link, how it would match against some sample inputs.
如果你想探索/简化/修改表达式,它已在regex101.com 的右上角面板中进行了 解释。如果您愿意,您还可以在此链接中观看它如何与某些示例输入匹配。
RegEx Circuit
正则表达式电路
jex.imvisualizes regular expressions:
jex.im可视化正则表达式:
回答by Jogai
A little improvement to Matthew's answer could be a lookahead instead of the last capturing group:
对马修答案的一点改进可能是前瞻而不是最后一个捕获组:
.replace(/(\w+)(\d+)(?=\w+)/, "!NEW_ID!");
Or you could split on the decimal and join with your new id like this:
或者你可以分割小数点并加入你的新 ID,如下所示:
.split(/\d+/).join("!NEW_ID!");
Example/Benchmark here: https://codepen.io/jogai/full/oyNXBX
示例/基准在这里:https: //codepen.io/jogai/full/oyNXBX
回答by CTS_AE
A simplier option is to just capture the digits and replace them.
一个更简单的选择是只捕获数字并替换它们。
const name = 'preceding_text_0_following_text';
const matcher = /(\d+)/;
// Replace with whatever you would like
const newName = name.replace(matcher, 'NEW_STUFF');
console.log("Full replace", newName);
// Perform work on the match and replace using a function
// In this case increment it using an arrow function
const incrementedName = name.replace(matcher, (match) => ++match);
console.log("Increment", incrementedName);