标签:javascript regex negative-lookahead
我有这个正则表达式搜索电话号码模式:
[(]?\d{3}[)]?[(\s)?.-]\d{3}[\s.-]\d{4}
这与以下格式匹配的电话号码:
123 456 7890
(123)456 7890
(123) 456 7890
(123)456-7890
(123) 456-7890
123.456.7890
123-456-7890
我想扫描整个页面(使用JavaScript)查找此匹配,但不包括已存在于锚内的此匹配.
找到匹配后,我想将电话号码转换为移动设备的点击呼叫链接:
(123) 456-7890 --> <a href="tel:1234567890">(123) 456-7890</a>
我很确定我需要进行否定查找.我试过这个,但这似乎不是一个正确的想法:
(?!.*(\<a href.*?\>))[(]?\d{3}[)]?[(\s)?.-]\d{3}[\s.-]\d{4}
解决方法:
Don’t use regular expressions to parse HTML.使用HTML / DOM解析器获取文本节点(浏览器可以为您过滤掉它,删除锚标签,所有文本都太短,不能包含电话号码),您可以直接检查文本.
例如,使用XPath(这有点难看,但支持直接处理文本节点,大多数其他DOM方法没有):
// This query finds all text nodes with at least 12 non-whitespace characters
// who are not direct children of an anchor tag
// Letting XPath apply basic filters dramatically reduces the number of elements
// you need to process (there are tons of short and/or pure whitespace text nodes
// in most DOMs)
var xpr = document.evaluate('descendant-or-self::text()[not(parent::A) and string-length(normalize-space(self::text())) >= 12]',
document.body, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
for (var i=0, len=xpr.snapshotLength; i < len; ++i) {
var txt = xpr.snapshotItem(i);
// Splits with grouping to preserve the text split on
var numbers = txt.data.split(/([(]?\d{3}[)]?[(\s)?.-]\d{3}[\s.-]\d{4})/);
// split will return at least three items on a hit, prefix, split match, and suffix
if (numbers.length >= 3) {
var parent = txt.parentNode; // Save parent before replacing child
// Insert new elements before existing element; first element is just
// text before first phone number
parent.insertBefore(document.createTextNode(numbers[0]), txt);
// Now explicitly create pairs of anchors and following text nodes
for (var j = 1; j < numbers.length; j += 2) {
// Operate in pairs; odd index is phone number, even is
// text following that phone number
var anc = document.createElement('a');
anc.href = 'tel:' + numbers[j].replace(/\D+/g, '');
anc.textContent = numbers[j];
parent.insertBefore(anc, txt);
parent.insertBefore(document.createTextNode(numbers[j+1]), txt);
}
// Remove original text node now that we've inserted all the
// replacement elements and don't need it for positioning anymore
parent.removeChild(txt);
parent.normalize(); // Normalize whitespace after rebuilding
}
}
为了记录,基本过滤器在大多数页面上都有很多帮助.例如,在这个页面上,现在,正如我所看到的(将根据用户,浏览器,浏览器扩展和脚本等因素而不同)没有过滤器,查询的快照’descendant-or-self :: text() ‘会有1794项.省略锚标记的主要文本,’descendant-or-self :: text()[not(parent :: A)]’将其降为1538,以及完整查询,验证非空白内容至少为12字符长达87项.将正则表达式应用于87个项目是笨拙的改变,性能方面,并且您已经无需使用不合适的工具解析HTML.
标签:javascript,regex,negative-lookahead 来源: https://codeday.me/bug/20191002/1842293.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。