使用正则表达式从html片段中提取文本,可匹配到多行但却只能捕获到最后一行,如何解决?

  • 正则表达式

    /^(?:<[pb]>)+((?:\w(\s)?)+:)(?:<\/[pb]>)+\n?(?:<p>((?:\w+\s*[,.:;()]?\s*)+)<\/p>\n?)+$/gm
  • 多行目标字符串
<p><b>Description:</b></p>
<p>This is a guitar accessory set includes 3pcs pickup covers, 1 volume and 2pcs knobs and 1 switch tip. Made of solid
    ABS plastic material. The covers are 48, 50 and 52mm spaced, fits for electric guitar. Great guitar accessory</p>
<p></p>
<p></p>
<p><b>Specification:</b></p>
<p>Made of ABS plastic material</p>
<p>Color: pink , Letter: White</p>
<p>Hole spacing: 48mm; 50mm; 52mm</p>
<p><b>Package Includes:</b></p>
<p>3 x Pickup cover</p>
<p>3 x Knob(1 volume knob and 2 knobs)</p>
<p>1 x Switch tip</p>
  • 匹配及捕获效果:
阅读 1.9k
avatarAI BotBETA

您提供的正则表达式有几个问题,这导致它不能正确地捕获您想要的多行文本。首先,正则表达式通常不建议用于解析HTML,因为HTML是一种复杂的嵌套结构,而正则表达式更擅长于处理线性文本。但是,如果您只是想要一个简单的解决方案,并且HTML结构是固定的,您可以尝试修改正则表达式来捕获所需的文本。

以下是针对您给出的HTML片段的一个简化正则表达式,它将尝试捕获<p>标签之间的文本:

/<p>([\s\S]*?)<\/p>/gm

这里的关键点是[\s\S]*?,它匹配任何字符(包括换行符),并且是非贪婪的(*?),这意味着它会尽可能少地匹配字符。这很重要,因为如果它是贪婪的(*),它将匹配尽可能多的字符,包括所有<p>标签之间的内容。

然而,请注意,这个正则表达式将捕获每个<p>标签的内容,而不是将它们组合在一起。如果您想要捕获连续的<p>标签的内容(例如,从“Description:”到“Great guitar accessory”),您将需要更复杂的逻辑,可能是使用正则表达式来查找起始和结束标签,然后使用编程逻辑来提取和组合这些标签之间的文本。

以下是使用JavaScript和DOM解析器来提取文本的一个例子,这通常是处理HTML内容的更可靠方法:

// 假设htmlString是包含HTML的字符串
var htmlString = '<p><b>Description:</b></p><p>This is a guitar ...'; // 您的HTML字符串
var parser = new DOMParser();
var doc = parser.parseFromString(htmlString, "text/html");

// 查找所有<p>标签并提取文本
var paragraphs = doc.getElementsByTagName('p');
var text = [];
for (var i = 0; i < paragraphs.length; i++) {
    // 移除任何HTML标签并添加到结果数组中
    text.push(paragraphs[i].textContent || paragraphs[i].innerText);
}

// 如果您想合并所有段落文本到一个字符串中
var allText = text.join('\n');

console.log(allText);

这种方法可以确保您正确地处理所有HTML元素,并且不会受到正则表达式在复杂HTML结构上的限制。

3 个回答
  1. 不要用正则匹配 HTML 这种强结构且高兼容性的文本,有很多现成的 DOM 树工具可以用。
  2. 中间的组本来就不能自动解开成数组,自己想办法分解吧。

xpath 匹配,香很多啊?

$ xidel test.html -e '/html/body/p/text()' --output-format json

结果:

[
  [
    "This is a guitar accessory set includes 3pcs pickup covers, 1 volume and 2pcs knobs and 1 switch tip. Made of solid\n    ABS plastic material. The covers are 48, 50 and 52mm spaced, fits for electric guitar. Great guitar accessory",
    "Made of ABS plastic material",
    "Color: pink , Letter: White",
    "Hole spacing: 48mm; 50mm; 52mm",
    "3 x Pickup cover",
    "3 x Knob(1 volume knob and 2 knobs)",
    "1 x Switch tip"
  ]
]

想捕获多行就把括号调整一下呗

/^(?:<[pb]>)+((?:\w\s?)+:)(?:<\/[pb]>)+\n?((?:<p>(?:(?:\w+\s*[,.:;()]?\s*)+)<\/p>\n?)+)$/gm
推荐问题