正则表达式 - 如何找到未被html标签包含或在它们之间包含的单词

时间:2011-06-12 15:17:16

标签: javascript html regex tags

我想在html字符串中找到匹配项。

这不会介于html标签之间或内部。

例如:

这个词是:ue

<span color=blue>ue</span>ue<span>sdfsd</span>

所以我想只找到第三场比赛(不在“蓝色”内)而不是span标签之间。

由于

4 个答案:

答案 0 :(得分:4)

您正在尝试使用正则表达式来解析HTML。 HTML 无法 可以使用正则表达式轻松,可靠地处理。

如果您在浏览器上执行此操作,则可以使用浏览器的高度优化的HTML解析器。

如果您想在中间有标签时检测到该字词(例如“u&lt; hr&gt; e”):

var element, node, topLevelText;
element = document.createElement('div');
element.innerHTML = "<span color=blue>ue</span>ue<span>sdfsd</span>";
topLevelText = "";
for (node = element.firstChild; node; node = node.nextSibling) {
    if (node.nodeType === 3) { // 3 = text node
        topLevelText += node.nodeValue;
    }
}
if (topLevelText.indexOf(word) >= 0) {
    // Found
}

如果你只是想在事物之间检测它(那么,你的例子而不是“你&lt; hr&gt; e”):

var element, node;
element = document.createElement('div');
element.innerHTML = "<span color=blue>ue</span>ue<span>sdfsd</span>";
for (node = element.firstChild; node; node = node.nextSibling) {
    if (node.nodeType === 3) { // 3 = text node
        if (node.nodeValue.indexOf(word) >= 0) {
            // Found
        }
    }
}

(两者都做区分大小写的匹配。)

这样做

  1. 使用document.createElement创建一个未在任何位置显示的元素。
  2. 通过将HTML文本分配给元素上的innerHTML来解析HTML文本。这个属性最近才被标准化,但它已被所有主流浏览器支持了十年左右。
  3. 查看节点的直接子节点,其中包括通过解析创建的任何元素,以及字符串中顶级文本的文本节点(例如,您要搜索它的位置中的文本)。这是使用Node#firstChildNode#nodeTypeNode#nodeValueNode#nextSibling
  4. 根据您是否想要在“u&lt; hr&gt; e”情况下找到它,它要么直接查看每个文本节点中的文本,要么将它们全部构建为字符串并在之后搜索。
  5. 上面的链接主要是DOM2 Core spec,大多数浏览器都支持这些链接。其他可以使用的参考文献:

答案 1 :(得分:4)

假设您正在处理HTML片段(而不是完整的文档),您可以编写正则表达式以匹配大多数格式良好的最内层非嵌套元素,然后递归应用此正则表达式以删除所有标记的材质,从标签之间留下所需的未标记材料。这里只是这样一个正则表达式(在注释的PHP / PCRE'x'语法中),它匹配大多数空的和非空的,非嵌套的,非短标签的HTML元素。

$re_html = '%# Match non-nested, non-shorttag HTML empty and non-empty elements.
    <                    # Opening tag opening "<" delimiter.
    (\w+)\b              # $1: Tag name.
    (?:                  # Non-capture group for optional attribute(s).
      \s+                # Attributes must be separated by whitespace.
      [\w\-.:]+          # Attribute name is required for attr=value pair.
      (?:                # Non-capture group for optional attribute value.
        \s*=\s*          # Name and value separated by "=" and optional ws.
        (?:              # Non-capture group for attrib value alternatives.
          "[^"]*"        # Double quoted string.
        | \'[^\']*\'     # Single quoted string.
        | [\w\-.:]+\b    # Non-quoted attrib value can be A-Z0-9-._:
        )                # End of attribute value alternatives.
      )?                 # Attribute value is optional.
    )*                   # Allow zero or more attribute=value pairs
    \s*                  # Whitespace is allowed before closing delimiter.
    (?:                  # This element is either empty or has close tag.
      />                 # Is either an empty tag having no contents,
    | >                  # or has both opening and closing tags.
      (                  # $2: Tag contents.
        [^<]*            # Everything up to next tag. (normal*)
        (?:              # We found a tag (open or close).
          (?!</?\1\b) <  # Not us? Match the "<". (special)
          [^<]*          # More of everything up to next tag. (normal*)
        )*               # Unroll-the-loop. (special normal*)*
      )                  # End $2. Tag contents.
      </\1\s*>           # Closing tag.
    )
    %x';

这是Javascript语法中的相同正则表达式:

var re_html = /<(\w+)\b(?:\s+[\w\-.:]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[\w\-.:]+\b))?)*\s*(?:\/>|>([^<]*(?:(?!<\/?\1\b)<[^<]*)*)<\/\1\s*>)/;

以下javascript函数剥离HTML元素,在标记之间留下所需的文本:

// Strip HTML elements.
function strip_html_elements(text) {
    // Match non-nested, non-shorttag HTML empty and non-empty elements.
    var re = /<(\w+)\b(?:\s+[\w\-.:]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[\w\-.:]+\b))?)*\s*(?:\/>|>([^<]*(?:(?!<\/?\1\b)<[^<]*)*)<\/\1\s*>)/g;
    // Loop removing innermost HTML elements from inside out.
    while (text.search(re) !== -1) {
        text = text.replace(re, '');
    }
    return text;
}

这个正则表达式解决方案不是一个合适的解析器,只处理只有html元素的简单HTML片段。它不能(也不能)正确处理具有注释,CDATA部分和doctype语句之类的更复杂的标记。它不会删除缺少其可选关闭标记的元素(即<p><li>元素。)

答案 2 :(得分:2)

HTML不是regular language,因此regular expressions无法对其进行解析。

答案 3 :(得分:2)

由于您在浏览器中具有出色的DOM操作可能性,因此您可以使用它。您可以创建一个新元素,将字符串设置为内容并迭代所有文本节点:

var tmp = document.createElement('div');
tmp.innerHTML = htmlString;

var matches = [],
    children = tmp.childNodes,
    node,
    word = ' ' + word + ' ';

for(var i = children.length; i--; ) {
    node = children[i];
    if(node.nodeType === 3 && (' ' + node.nodeValue + ' ').indexOf(word) > -1) {
        matches.push(node);
    }
}