这个想法是在一个字符串中替换所有十进制数字,而小数点前的数字为零,因此.03 sqrt(.02)
将成为0.03 sqrt(0.02)
。
请参阅下面的代码示例,问题是当小数点前面有一个替换时,替换会覆盖左括号。我认为括号与匹配字符串无关,是吗?
let s='.05 sqrt(.005) another(.33) thisShouldntChange(a.b) neither(3.4)'
s=s.replace(/(?:^|\D)\.(\d+)/g , "0.$1");
console.log(s)
答案 0 :(得分:1)
进行初始群组捕获,而不是非捕获,并在替换中使用它:
s=s.replace(/(^|[^\d])\.(\d+)/g , "$10.$2");
// ^---- capturing, not non-capturing
示例:
let s = '.05 sqrt(.005) another(.33) thisShouldntChange(a.b) neither(3.4)'
s=s.replace(/(^|[^\d])\.(\d+)/g , "$10.$2");
console.log(s)
我认为括号与匹配字符串无关,是吗?
确实如此,因为它匹配[^\d]
。
附注:As Wiktor points out,您可以使用\D
代替[^\d]
。
附注2:JavaScript正则表达式最终获得lookbehind(在living specification中,并且将在ES2018规范快照中),因此使用现代 JavaScript环境将是负面的背后:
s=s.replace(/(?<!\d)\.(\d+)/g , "0.$1");
// ^^^^^^^--- negative lookbehind for a digit
这基本上意味着“如果这里有一个数字,那就不匹配了”。 (还有肯定的 lookbehind,(?<=...)
。)
示例:
let s = '.05 sqrt(.005) another(.33) thisShouldntChange(a.b) neither(3.4)'
s=s.replace(/(?<!\d)\.(\d+)/g , "0.$1");
console.log(s)
答案 1 :(得分:1)
括号是一个nn数字,因此它与[^\d]
匹配并删除。
解决方案是在点之前匹配并捕获零件,然后使用替换后向引用插回。
使用
.replace(/(^|\D)\.(\d+)/g , "$10.$2")
请参阅regex demo。
模式详情
(^|\D)
- 捕获第1组(稍后从替换模式中引用$1
):字符串的开头或任何非数字([^\d]
= \D
) \.
- 一个点(\d+)
- 捕获第2组(后来用替换模式中的$2
引用):1+位。参见JS演示:
let s='.05 sqrt(.005) another(.33) thisShouldnt(a.b) neither(3.4)'
s=s.replace(/(^|\D)\.(\d+)/g , "$10.$2");
console.log(s)
请注意,$10.$2
将由RegExp引擎解析为$1
反向引用,然后是0.
文本,然后是$2
反向引用,因为在此只有2个捕获组模式,没有10个捕获组,因此$10
不会被视为替换模式中的有效标记。