如何仅替换捕获的组?


194

我在字符串前后有HTML代码:

name="some_text_0_some_text"

我想将替换为0!NEW_ID!

所以我做了一个简单的正则表达式:

.*name="\w+(\d+)\w+".*

但是我看不到如何专门替换捕获的块。

有没有办法用其他字符串替换捕获的结果($ 1)?

结果将是:

name="some_text_!NEW_ID!_some_text"

Answers:


358

一种解决方案是为前面和后面的文本添加捕获:

str.replace(/(.*name="\w+)(\d+)(\w+".*)/, "$1!NEW_ID!$3")

76
未来的问候!您的解决方案看起来很整洁。你能解释一下你的答案吗?
Polyducks

21
括号用于创建“组”,然后$为该(\w+)组分配基数为1的索引,可以用a替换该索引,因此第一个单词在组中,并且变为$1,中间部分(\d+)是第二组,(但在替换中忽略),而第三组是$3。因此,当您提供替换字符串时"$1!new_ID!$3",$ 1和$ 3会自动被第一组和第三组替换,从而允许第二组被新字符串替换,并保持其周围的文本。
mix3d

4
话虽这么说,但我了解它是如何工作的,但我希望有一个更优雅的解决方案>。<不过,我现在可以继续编写我的代码了!
mix3d

9
1)您甚至不需要捕获\ d + 2)为什么您说它不优雅?捕获是为了保留东西,而不是将其丢弃。您想要保留的是\ d +周围的东西,因此捕获周围的部分确实很有意义(足够优雅)。
Sir4ur0n

3
不错的解决方案。如果我们要使用捕获组作为转换的基础来替换捕获组怎么办?是否有同样优雅的解决方案?目前,我将捕获的组存储在一个列表中,进行循环,然后在每次迭代时将捕获的组替换为转换后的值
sookie

15

现在(从ES2018开始)Javascript已经落后了,在较新的环境中,您可以完全避免在此类情况下进行分组。相反,回顾后为你捕捉组之前会发生什么,以及超前的来后,并将其替换只是 !NEW_ID!

const str = 'name="some_text_0_some_text"';
console.log(
  str.replace(/(?<=name="\w+)\d+(?=\w+")/, '!NEW_ID!')
);

使用这种方法,完全匹配只是需要替换的部分。

  • (?<=name="\w+)-Lookbehind for name",后跟单词字符(幸运的是,lookbehinds在Javascript中不必固定宽度!)
  • \d+ -匹配一个或多个数字-模式的唯一部分不在环视范围内,字符串的唯一部分将出现在结果匹配项中
  • (?=\w+")-前瞻单词字符,后跟" `

请记住,向后看是很新的。它可以在V8的现代版本(包括Chrome,Opera和Node)中运行,但在大多数其他环境中(至少目前还不能)使用。因此,尽管您可以在Node和自己的浏览器中可靠地使用lookbehind(如果它在V8的现代版本上运行),但随机客户端(例如在公共网站上)尚不能提供足够的支持。


只需运行一个快速的时序测试,输入的重要性
Kaiido

但是,例如,如果我想提取数字,倍数并“放回去”,那么我也必须分组\d+,对吗?
Mosh Feu

@MoshFeu使用替换函数并使用整个匹配项,即数字:用替换第二个参数match => match * 2。这些数字仍然是完整的比赛,因此无需分组
SomePerformance

知道了 谢谢!
Mosh Feu

2

对Matthew答案的一点改进可以是先行,而不是最后一个捕获组:

.replace(/(\w+)(\d+)(?=\w+)/, "$1!NEW_ID!");

或者,您可以分割小数点并加入新的ID,如下所示:

.split(/\d+/).join("!NEW_ID!");

此处的示例/基准:https//codepen.io/jogai/full/oyNXBX


1

如果有两个捕获组,也将是可能的;我还要在数字的前后添加两个破折号,作为附加的左右边界,修改后的表达式将如下所示:

(.*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 = `$1!NEW_ID!$2`;
const result = str.replace(regex, subst);
console.log(result);


如果您想浏览/简化/修改该表达式,请在regex101.com的右上方面板中进行 说明。如果愿意,您还可以在此链接中观看,它将如何与某些示例输入匹配。


RegEx电路

jex.im可视化正则表达式:

在此处输入图片说明


0

一个更简单的选择是只捕获数字并替换它们。

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);

资源资源

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.