我有一根看起来像
var std = new Bammer({mode:"deg"}).bam(0, 112).bam(177.58, (line-4)/2).bam(0, -42)
.ramBam(8.1, 0).bam(8.1, (slot_height-thick)/2)我想在最后一个.bam()或.ramBam()周围加上一个标签。
str.replace(/(\.(ram)?bam\(.*?\))$/i, '<span class="focus">$1</span>');我希望能得到:
new Bammer({mode:"deg"}).bam(0, 112).bam(177.58, (line-4)/2).bam(0, -42).ramBam(8.1, 0)<span class="focus">.bam(8.1, (slot_height-thick)/2)</span>但不知何故,我继续与非贪婪的参数战斗,它用span标签包装了新的Bammer之后的一切。在$之前也尝试了一个问号,以使小组不贪婪。
我希望能简单地做到这一点,使用bam或ramBam,我认为正则表达式是最简单的解决方案,但我认为我错了。
我哪里出问题了?
发布于 2020-03-10 23:20:14
您可以使用以下正则表达式:
(?!.*\)\.)(\.(?:bam|ramBam)\(.*\))$(?!.*\)\.) # do not match ').' later in the string
( # begin capture group 1
.\ # match '.'
(?:bam|ramBam) # match 'bam' or 'ramBam' in non-cap group
\(.*\) # match '(', 0+ chars, ')'
) # end capture group 1
$ # match end of line对于问题中给出的示例,负前瞻性(?!.*\)\.)将内部指针移动到子字符串之前:
.bam(8.1, (slot_height-thick)/2)因为这是字符串后面没有子字符串).的第一个位置。
如果没有行尾锚$并且字符串结束:
...0).bam(8.1, (slot_height-thick)/2)abc然后,仍将进行替换,从而生成一个字符串,该字符串的结尾为:
...0)<span class="focus">.bam(8.1, (slot_height-thick)/2)</span>abc如果字符串没有以预期捕获组的内容结束,则包括行尾锚将防止替换。
发布于 2020-03-10 21:10:51
使用要求:
/\.((?:ram)?[bB]am\([^)]*\))(?!.*\.(ram)?[bB]am\()/\.匹配周期。(?:ram)?可选择匹配非捕获组中的ram。[bB]am与bam或Bam匹配。\(与(匹配。[^)]*匹配0或多个字符,只要它们不是)。)与)匹配。项目2至6.置于捕获组1中。(?!.*\.(ram)?[bB]am\() --这是一个负的前瞻性断言,说明字符串的其余部分不包含.ram(、.rambam(或.ramBam(的进一步实例,因此这是最后一个实例。
let str = 'var std = new Bammer({mode:"deg"}).bam(0, 112).bam(177.58, 0).bam(0, -42).ramBam(8.1, 0).bam(8.1, slot_height)';
console.log(str.replace(/\.((?:ram)?[bB]am\([^)]*\))(?!.*\.(ram)?[bB]am\()/, '<span class="focus">.$1</span>'));
更新
JavaScript正则表达式引擎不够强大,无法处理嵌套括号。解决这个问题的唯一方法是,假设在最后调用bam或ramBam之后,字符串中没有多余的右括号。然后,在使用\([^)]*\)扫描括号大小的表达式时,如果不能选择最后的括号,我们现在必须使用\(.*\)扫描所有内容,直到最后的括号。至少我不知道其他方法。但这也意味着,我使用负前瞻性来确定ram或ramBam的最终实例的方式需要稍作调整。在开始执行任何贪婪的匹配之前,我需要确保拥有ram或ramBam的最后实例:
(\.(?:bam|ramBam)(?!.*\.(bam|ramBam)\()\((.*)\))\.与.匹配。(?:bam|ramBam)匹配bam或ramBam。(?!.*\.(bam|ramBam)\()断言第1项是最终实例\(与(匹配。(.*)贪婪地匹配一切直到..。\) )。)项目1至6.放置在捕获组1中。
let str = 'var std = new Bammer({mode:"deg"}).bam(0, 112).bam(177.58, (line-4)/2).bam(0, -42) .ramBam(8.1, 0).bam(8.1, (slot_height-thick)/2)';
console.log(str.replace(/(\.(?:bam|ramBam)(?!.*\.(bam|ramBam)\()\((.*)\))/, '<span class="focus">$1</span>'));
发布于 2020-03-10 20:59:56
非贪婪的标志并不完全正确,因为这只会使正则表达式选择最小数量的字符来适应模式。我建议你用这样的负前瞻做点什么:
str.replace(/(\.(?:ram)?[Bb]am\([^)]*\)(?!.*(ram)?[Bb]am))/i, '<span class="focus">$1</span>');请注意,这只会替换最后一个函数名(bam或ramBam),而不是两者都替换。您需要采取一种稍微不同的方法来替换这两种方法。
https://stackoverflow.com/questions/60625719
复制相似问题