正则表达式匹配除<p>和</ p>之外的所有HTML标记

Xet*_*ius 22 html regex perl

我需要使用Perl中的正则表达式匹配并删除所有标记.我有以下内容:

<\\??(?!p).+?>
Run Code Online (Sandbox Code Playgroud)

但这仍然与结束</p>标签相匹配.关于如何与结束标签匹配的任何提示?

注意,这是在xhtml上执行的.

Joh*_*usa 37

如果你坚持使用正则表达式,这样的东西在大多数情况下都会起作用:

# Remove all HTML except "p" tags
$html =~ s{<(?>/?)(?:[^pP]|[pP][^\s>/])[^>]*>}{}g;
Run Code Online (Sandbox Code Playgroud)

说明:

s{
  <             # opening angled bracket
  (?>/?)        # ratchet past optional / 
  (?:
    [^pP]       # non-p tag
    |           # ...or...
    [pP][^\s>/] # longer tag that begins with p (e.g., <pre>)
  )
  [^>]*         # everything until closing angled bracket
  >             # closing angled bracket
 }{}gx; # replace with nothing, globally
Run Code Online (Sandbox Code Playgroud)

但实际上,为自己省去一些麻烦并改为使用解析器.CPAN有几个适合的模块.下面是一个使用HTML :: TokeParser模块的示例,该模块附带了非常强大的HTML :: Parser CPAN发行版:

use strict;

use HTML::TokeParser;

my $parser = HTML::TokeParser->new('/some/file.html')
  or die "Could not open /some/file.html - $!";

while(my $t = $parser->get_token)
{
  # Skip start or end tags that are not "p" tags
  next  if(($t->[0] eq 'S' || $t->[0] eq 'E') && lc $t->[1] ne 'p');

  # Print everything else normally (see HTML::TokeParser docs for explanation)
  if($t->[0] eq 'T')
  {
    print $t->[1];
  }
  else
  {
    print $t->[-1];
  }
}
Run Code Online (Sandbox Code Playgroud)

HTML :: Parser以文件名,打开文件句柄或字符串的形式接受输入.将上述代码包装在库中并使目标可配置(即,不仅仅是print如上所述)并不难.与尝试使用正则表达式相比,结果将更可靠,可维护,并且可能也更快(HTML :: Parser使用基于C的后端).


Jör*_*tag 16

在我看来,试图用HTML解析器以外的任何东西解析HTML只是在寻求一个痛苦的世界.HTML是一种非常复杂的语言(这是创建XHTML的主要原因之一,它比HTML简单得多).

例如,这个:

<HTML /
  <HEAD /
    <TITLE / > /
    <P / >
Run Code Online (Sandbox Code Playgroud)

是一个完整的,100%格式良好,100%有效的HTML文档.(好吧,它缺少DOCTYPE声明,但除此之外......)

它在语义上等同于

<html>
  <head>
    <title>
      &gt;
    </title>
  </head>
  <body>
    <p>
      &gt;
    </p>
  </body>
</html>
Run Code Online (Sandbox Code Playgroud)

但是,您将不得不处理有效的HTML.当然,您可以设计一个正则表达式来解析它,但是,正如其他人已经建议的那样,使用实际的HTML解析器要简单得多.


Xet*_*ius 11

我想出了这个:

<(?!\/?p(?=>|\s.*>))\/?.*?>

x/
<           # Match open angle bracket
(?!         # Negative lookahead (Not matching and not consuming)
    \/?     # 0 or 1 /
    p           # p
    (?=     # Positive lookahead (Matching and not consuming)
    >       # > - No attributes
        |       # or
    \s      # whitespace
    .*      # anything up to 
    >       # close angle brackets - with attributes
    )           # close positive lookahead
)           # close negative lookahead
            # if we have got this far then we don't match
            # a p tag or closing p tag
            # with or without attributes
\/?         # optional close tag symbol (/)
.*?         # and anything up to
>           # first closing tag
/
Run Code Online (Sandbox Code Playgroud)

现在,这将处理带有或不带属性的p标签和关闭p标签,但会匹配pre和类似标签,有或没有属性.

它没有删除属性,但是我的源数据没有将它们放入.我可能会在稍后更改它,但这就足够了.


y_n*_*_nk 5

我使用了 Xetius 正则表达式,效果很好。除了一些 Flex 生成的标签之外,这些标签可以是 :
且内部没有空格。我尝试用简单的方法修复它\s之后,看起来它正在工作:

<(?!\/?p(?=>|\s?.*>))\/?.*?>
Run Code Online (Sandbox Code Playgroud)

我用它来清除 Flex 生成的 html 文本中的标签,因此我还添加了更多例外标签:

<(?!\/?(p|a|b|i|u|br)(?=>|\s?.*>))\/?.*?>
Run Code Online (Sandbox Code Playgroud)