JavaScript 字符串替换中的子匹配组引用是不是有分隔符/消歧语法?

Posted

技术标签:

【中文标题】JavaScript 字符串替换中的子匹配组引用是不是有分隔符/消歧语法?【英文标题】:Is there a delimiter/disambiguation syntax for submatch group references in JavaScript string replacement?JavaScript 字符串替换中的子匹配组引用是否有分隔符/消歧语法? 【发布时间】:2021-04-29 03:22:25 【问题描述】:

这肯定在某个地方已经有了答案,但我什至不知道要搜索什么。

javascript 中,我可以在替换字符串中引用带括号的子匹配,如下所示:

"abcdefghijklmnopqrstuvwxyz".replace(/(.)/g, "$1-");
// Result: "a-b-c-d-e-f-g-h-i-j-k-l-m-n-o-p-q-r-s-t-u-v-w-x-y-z-"

现在,我想在每个字母之间添加 1 而不是 -

"abcdefghijklmnopqrstuvwxyz".replace(/(.)/g, "$11");
// Result: "a1b1c1d1e1f1g1h1i1j1k1l1m1n1o1p1q1r1s1t1u1v1w1x1y1z1"

至少 Chromium 似乎检测到没有子匹配组 11,因此它将替换字符串解释为“子匹配组 1 后跟 1”。

我们假设有 11 个组:

'abcdefghijklmnopqrstuvwxyz'.replace(/^(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)$/, '$11');
// Result: "k"

我想知道的:

示例 2 是否可以跨浏览器工作?它是否在某个地方定义了它应该表现得像这样? 有没有办法明确界定子匹配组引用?在 bash 中,$a$a 指的是同一个变量,但后者可以将其与以下文本分隔开来。可以让我将示例 3 输出为 "a1" 而不是“k”。

【问题讨论】:

【参考方案1】:

JavaScript 正则表达式引擎假定$ 之后的最长数字序列是要引用的组 ID,前提是模式中有这样的组,因此如果模式中有一个组,$111 将引用组 111,或者到第 11 组和1(如果有第 11 组),或者到第 1 组和11(如果少于 11 个组)。如果根本没有组,它将作为文字字符串返回(即"x".replace(/./g, "$1") 返回$1)。

console.log('abcdefghijklmnopqrstuvwxyz'.replace(/^(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)$/, '$11')); // => "k"
console.log('abcdefghijklmnopqrstuvwxyz'.replace(/^(.)(.)(.)(.)(.)(.)(.)(.)(.).................$/, '$11')); // => "a1"

如果您知道在您的模式中引用组时可能存在歧义,您可以用零填充组 ID

$011 将作为对第 1 组和1 的反向引用消除歧义:

console.log('abcdefghijklmnopqrstuvwxyz'.replace(/^(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)$/, '$011')); // => "a1"

不过,你也可以使用named capturing groups with named backreferences

console.log('abcdefghijklmnopqrstuvwxyz'.replace(/^(?<name>.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)$/, '$<name>1')); // => "a1"

Table 54: Replacement Text Symbol Substitutions table 中,反向引用语法定义为$n$nn,但是,即使$nnn 语法也是允许的。

Code units Unicode Characters Replacement text
0x0024, N Where 0x0031 ≤ N ≤ 0x0039 $n where n is one of 1 2 3 4 5 6 7 8 9 and $n is not followed by a decimal digit The nth element of captures, where n is a single digit in the range 1 to 9. If nm and the nth element of captures is undefined, use the empty String instead. If n > m, no replacement is done.
0x0024, N, N Where 0x0030 ≤ N ≤ 0x0039 $nn where n is one of 0 1 2 3 4 5 6 7 8 9 The nnth element of captures, where nn is a two-digit decimal number in the range 01 to 99. If nnm and the nnth element of captures is undefined, use the empty String instead. If nn is 00 or nn > m, no replacement is done.

【讨论】:

以上是关于JavaScript 字符串替换中的子匹配组引用是不是有分隔符/消歧语法?的主要内容,如果未能解决你的问题,请参考以下文章

Javascript参考匹配组替换?

查找和替换文件中与另一个文件中的字符串匹配的子字符串

JavaScript正则表达式修饰符

JavaScript 正则表达式

使用javascript替换textarea中所有行中的子字符串

将双括号内的子字符串替换为javascript中的不同字符串