如何仅替换捕获的组?

我有HTML代码之前和之后的字符串:

name="some_text_0_some_text"

我想用类似!NEW_ID!的东西替换0

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

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

但是我不知道如何专门替换捕获的块。

是否有一种方法替换捕获的结果,如($1)与其他字符串?

结果将是:

name="some_text_!NEW_ID!_some_text"
221673 次浏览

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

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

解释

圆括号用于创建“;groups”,然后为其分配以1为基数的索引,可在替换为$时访问。

  • 第一个单词(\w+)在一个组中,并变成$1
  • 中间部分(\d+)是第二组(但在replace中被忽略)
  • 第三组(\w+".*)变成$3

因此,当你给出替换字符串"$1!new_ID!$3"时,$1$3会自动被第一组和第三组替换,允许第二组被新字符串替换,并保留它周围的文本。

对马太的答案稍加改进,可以是一个前瞻,而不是最后一个捕捉组:

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

或者你可以在小数点上拆分,并像这样与你的新id连接:

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

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

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

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

资源

现在Javascript有了追溯功能(从ES2018开始),在更新的环境中,你可以在这样的情况下完全避免分组。相反,向后看你所捕捉的组之前发生了什么,并向前看之后发生了什么,并用只是 !NEW_ID!替换:

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

使用此方法,完全匹配是只有,即需要替换的部分。

  • (?<=name="\w+) -查找name="的后面,后面跟着单词字符(幸运的是,在Javascript中查找的后面不需要固定宽度!)
  • \d+ -匹配一个或多个数字-模式中唯一不在查找中的部分,字符串中唯一将在结果匹配中的部分
  • (?=\w+") -查找后跟"的word字符 李的< / >

请记住,向后看是相当新的。它可以在现代版本的V8(包括Chrome、Opera和Node)中工作,但在其他大多数环境中都不是这样,至少目前还不行。因此,虽然你可以在Node和你自己的浏览器中可靠地使用向后查找(如果它运行在V8的现代版本上),但它还没有被随机客户端(比如公共网站)充分支持。

如果有两个捕获组也是可能的;我还会包括两个破折号,作为额外的左右边界,在数字之前和之后,修改后的表达式将看起来像:

(.*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。如果你愿意,你可以 也可以在这 Link ,如何匹配


RegEx电路

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

enter image description here

"some_text_0_some_text".replace(/(?=\w+)\d+(?=\w+)/, '!NEW_ID!')

结果是

some_text_ NEW_ID !_some_text

const regExp = /(?=\w+)\d+(?=\w+)/;
const newID = '!NEW_ID!';
const str = 'some_text_0_some_text';
const result = str.replace(regExp, newID);


console.log(result);

x(?=y)在JS RegExp

< p >匹配“x"只有当"x"后面跟着"y"例如,/Jack(?=Sprat)/匹配“Jack"除非后面跟着“Sprat"”。 /Jack(?=Sprat|Frost)/匹配“jack”;除非它后面跟着"Sprat"或“;Frost"。然而,“Sprat"也不是“Frost"是匹配结果的一部分。

details

要知道,如果需要转换和操作捕获组,可以使用转换器函数作为第二个参数……

API

replace(
regex,
(matched, capture1, capture2, /*...,*/ capture_n, index, input_str) => transformed(/*...*/)
)
replace(
regex: Regex,
transformer: (matched: string, capture1: string, capture2: string, /*...,*/ capture_n: string, index: number, input_str: string) => string
) => string

捕获的数量与您在正则表达式中使用的数量相关。indexinput_str是最后一个。

请参阅下面的示例及其输出,以更好地了解每个示例的含义。

医生参考:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#making_a_generic_replacer

例子:

// To uses example
const propsArgs = args.map((arg) =>
arg.slice(2).replace(/-(.)/g, (matched, captureGroup, index, input) => {
return captureGroup.toUpperCase();
})
);




// To uses example multiple captures groups
const propsArgs = args.map((arg) =>
arg
.slice(2)
.replace(/-(.)(.)/g, (matched, capture1, capture2, index, input) => {
return capture2.toUpperCase();
})
);


// To uses example multiple captures groups args destructuring version
// args[0] matched, args[1] capture 1, ....., args[n] capture n, args[n+1] index, args[n+2] total string to replace.
const propsArgs = args.map((arg) =>
arg.slice(2).replace(/-(.)(.)/g, (...args) => {
return args[2].toUpperCase(); // capture 2
})
);


// example for understanding
const propsArgs = args.map((arg) =>
arg.slice(2).replace(/-(.)/g, (...args) => {
console.log(args); // [ '-f', 'f', 6, 'config-file' ]
return args[1].toUpperCase();
})
);


// multiple capture groups and the args order
/**
* matched string, then all the captures arg after another, then index, then total input string to replace
*/
const propsArgs = args.map((arg) =>
arg
.slice(2)
.replace(
/-(.)(.)(.)/g,
(matched, capture1, capture2, capture3, index, input) => {
// [ '-wat', 'w', 'a', 't', 3, 'log-watch-compilation' ]
return capture1.toUpperCase();
}
)
);

上面的核心示例是将命令行参数转换为javascript的驼峰格式。

转换:

[
'--filename',
'--config-file',
'--env-name',
'--no-swcrc',
'--ignore',
'--only',
'--watch',
'--quiet',
'--source-maps',
'--source-map-target',
'--source-file-name',
'--source-root',
'--out-file',
'--out-dir',
'--copy-files',
'--include-dotfiles',
'--config',
'--sync',
'--log-watch-compilation',
'--extensions'
]

[
'filename',            'configFile',
'envName',             'noSwcrc',
'ignore',              'only',
'watch',               'quiet',
'sourceMaps',          'sourceMapTarget',
'sourceFileName',      'sourceRoot',
'outFile',             'outDir',
'copyFiles',           'includeDotfiles',
'config',              'sync',
'logWatchCompilation', 'extensions'
]