首页 > 解决方案 > 用于查找元素标记名和属性的正则表达式“跳过”属性

问题描述

我正在尝试创建一个正则表达式来查找元素的标记名和属性。例如,如果我有这个:

<div id="anId" class="aClass">

我希望能够得到一个看起来像这样的数组:

["(full match)", "div", "id", "anId", "class", "aClass"]

目前,我有 regex /<(\S*?)(?: ?(.*?)="(.*?)")*>/,但由于某种原因,它跳过了除最后一个之外的所有属性。

var str = '<div id="anId" class="aClass">'
console.log(str.match(/<(\S*)(?: ?(.*?)="(.*?)")*>/));

正则表达式101: https ://regex101.com/r/G0ncwF/2

另一个奇怪的事情:如果我*在非捕获组之后删除,引号中的捕获组似乎以某种方式“忘记”它是懒惰的。(正则表达式101: https ://regex101.com/r/C0UwI8/2 )

为什么会发生这种情况,我该如何避免?我找不到任何对我有帮助的问题/答案(Python re.finditer match.groups() 不包含 match 中的所有组看起来很有希望,但似乎根本没有帮助我)

(注意:我知道有更好的方法来获取属性,我只是在尝试使用正则表达式)

更新:

我至少弄清楚了为什么量词似乎“忘记”了他们是懒惰的。实际上只是正则表达式一直试图匹配尖括号。我想我一定一直认为非捕获组正在“隔离”一切并防止这种情况发生,我没有看到它仍然很懒,因为它只有一个尖括号可以找到。

var str = '"foo" "bar"> "baz>"'
console.log("/\".*?\"/ produces ", str.match(/".*?"/), ", finds first quote, finds text, lazily stops at second quote");
console.log("/\".*?\">/ produces ", str.match(/".*?">/), ", finds first quote, finds text, sees second quote but doesn't see angle bracket, keeps going until it sees \">, lazily stops");

所以至少这已经解决了。但我仍然不明白为什么它会跳过除最后一个之外的所有属性。

并注意:其他使用不同技巧来查找属性的正则表达式都很好,但我主要想了解为什么我的正则表达式会跳过属性,所以我可能会更好地理解正则表达式。

标签: javascriptregex

解决方案


与你的实验一起玩,你可以这样做:你可以扫描你不想要的东西,而不是扫描你想要的东西,然后将其过滤掉:

const html = '<div id="anId" class="aClass">';
const regex = /[<> ="]/;
let result = html.split(regex).filter(Boolean);
console.log('result: '+JSON.stringify(result));

输出:

result: ["div","id","anId","class","aClass"]

解释:

  • 正则表达式/[<> ="]/列出您不想要的所有字符
  • .split(regex)沿不需要的字符拆分您的文本
  • .filter(Boolean)摆脱不需要的字符

请注意,这有缺陷,例如它会为 html 错误地拆分<div id="anId" class="aClass anotherClass">,例如属性值中的空格。为了支持这一点,您可以使用另一个正则表达式预处理 html 以转义引号中的空格,然后使用另一个正则表达式进行后处理以恢复空格...

是的,对于这类任务,HTML 解析器更可靠。


推荐阅读