Jac*_*kie 4 javascript regex regex-lookarounds
考虑:
var re = /(?<=foo)bar/gi;
Run Code Online (Sandbox Code Playgroud)
它是Plunker中的无效正则表达式.为什么?
Ada*_*atz 15
JavaScript缺乏对(正面)和(负面)等外观的支持,但这并不意味着你仍然无法在JavaScript中实现这种逻辑.(?<=…)(?<!…)
// from /(?<=foo)bar/i
var matcher = mystring.match( /foo(bar)/i );
if (matcher) {
// do stuff with matcher[1] which is the part that matches "bar"
}
Run Code Online (Sandbox Code Playgroud)
// from /(?<!foo)bar/i
var matcher = mystring.match( /(?!foo)(?:^.{0,2}|.{3})(bar)/i );
if (matcher) {
// do stuff with matcher[1] ("bar"), knowing that it does not follow "foo"
}
Run Code Online (Sandbox Code Playgroud)
负面观察可以在没有全局标志的情况下完成,但只能使用固定宽度,并且您必须计算该宽度(这可能会因交替而变得困难).使用(?!foo).{3}(bar)将更简单和大致相同,但它不匹配以"钢筋"开头的.行,因为无法匹配换行符,因此我们需要上述代码的交替来匹配在字符四之前具有"bar"的行.
如果您需要宽度可变,请使用以下全局解决方案并break在该if节的末尾添加一个.(此限制是相当普遍的. .NET,VIM,和JGsoft是唯一的正则表达式引擎支持可变宽度回顾后发. PCRE,PHP,和Perl中被限制为固定的宽度. Python中需要一个备用模块的正则表达式来支持这一点.这就是说,下面的解决方法的逻辑应适用于支持正则表达式的所有语言.)
当你需要循环给定字符串中的每个匹配(g修饰符,全局匹配)时,你必须matcher在每个循环迭代中重新定义变量,你必须使用RegExp.exec()(在循环之前创建RegExp )因为不同地String.match()解释全局修饰符和将创造一个无限循环!
var re = /foo(bar)/gi; // from /(?<=foo)bar/gi
while ( matcher = re.exec(mystring) ) {
// do stuff with matcher[1] which is the part that matches "bar"
}
Run Code Online (Sandbox Code Playgroud)
"Stuff"当然可以包括填充阵列以供进一步使用.
var re = /(foo)?bar/gi; // from /(?<!foo)bar/gi
while ( matcher = re.exec(mystring) ) {
if (!matcher[1]) {
// do stuff with matcher[0] ("bar"), knowing that it does not follow "foo"
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,在某些情况下,这并不能完全代表负面的背后.考虑/(?<!ba)ll/g匹配Fall ball bill balll llama.它只能找到所需的四个匹配中的三个,因为当它解析时balll,它会找到ball并继续一个字符l llama.这只发生在末端的部分匹配可能干扰不同端的部分匹配时(balll中断(ba)?ll但foobarbar很好(foo)?bar)唯一的解决方法是使用上述固定宽度方法.
在JavaScript中有一篇名为Mimicking Lookbehind的精彩文章描述了如何做到这一点.
它甚至还有一个后续内容,指向在JS中实现此功能的一组简短函数.
实现lookbehind in String.replace()更容易,因为您可以创建一个匿名函数作为替换并处理该函数中的lookbehind逻辑.
这些工作在第一次匹配时,但只需添加g修饰符就可以使其全局化.
// assuming you wanted mystring.replace(/(?<=foo)bar/i, "baz"):
mystring = mystring.replace( /(foo)?bar/i,
function ($0, $1) { return ($1 ? $1 + "baz" : $0) }
);
Run Code Online (Sandbox Code Playgroud)
这需要目标字符串并替换的情况下,bar与baz,只要他们遵循foo.如果$1匹配,则三元运算符(?:)返回匹配的文本和替换文本(但不返回bar部分).否则,三元运算符返回原始文本.
// assuming you wanted mystring.replace(/(?<!foo)bar/i, "baz"):
mystring = mystring.replace( /(foo)?bar/i,
function ($0, $1) { return ($1 ? $0 : "baz") }
);
Run Code Online (Sandbox Code Playgroud)
这基本上是相同的,但由于它是一个负面的背后,它在$1失踪时起作用(我们不需要在$1 + "baz"这里说因为我们知道$1是空的).
这与其他动态宽度负向后视解决方法具有相同的警告,并且通过使用固定宽度方法类似地修复.
这是一种在 JS 中使用 DOM 解析 HTML 字符串并仅在标签之外执行替换的方法:
var s = '<span class="css">55</span> 2 >= 1 2 > 1';
var doc = document.createDocumentFragment();
var wrapper = document.createElement('myelt');
wrapper.innerHTML = s;
doc.appendChild( wrapper );
function textNodesUnder(el){
var n, walk=document.createTreeWalker(el,NodeFilter.SHOW_TEXT,null,false);
while(n=walk.nextNode())
{
if (n.parentNode.nodeName.toLowerCase() === 'myelt')
n.nodeValue = n.nodeValue.replace(/>=?/g, "EQUAL");
}
return el.firstChild.innerHTML;
}
var res = textNodesUnder(doc);
console.log(res);
alert(res);Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4686 次 |
| 最近记录: |