【问题标题】:regex to match html tags with specific attributes正则表达式匹配具有特定属性的 html 标签
【发布时间】:2012-02-18 23:23:21
【问题描述】:

我正在尝试匹配所有没有属性“term”或“range”的 HTML 标记

这里是示例 HTML 格式

<span class="inline prewrap strong">DATE:</span>    12/01/10
<span class="inline prewrap strong">MR:</span>  1234567
<span class="inline prewrap strong">DOB:</span> 12/01/65
<span class="inline prewrap strong">HISTORY OF PRESENT ILLNESS:</span>  Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum

<span class="inline prewrap strong">MEDICATIONS:</span>  <span term="Advil" range="true">Advil </span>and Ibuprofen.

我的正则表达式是:&lt;(.*?)((?!\bterm\b).)&gt;

不幸的是,这匹配了所有标签...如果内部文本不匹配,那就太好了,因为我需要过滤掉除具有特定属性的标签之外的所有标签。

【问题讨论】:

  • 您能否详细说明您正在尝试做什么?您是要过滤掉所有具有“术语”或“范围”属性的标签,还是所有没有“术语”或“范围”属性的标签?
  • 我正在尝试过滤掉所有没有“term”和“range”属性的标签。基本上在我做了一个 replace() 之后,只有具有这些属性的标签应该仍然存在。

标签: regex pattern-matching string-matching


【解决方案1】:

我认为这个正则表达式可以正常工作。

此正则表达式将选择任何 HTML 标记的样式属性。

<\s*\w*\s*style.*?>

你可以在https://regex101.com查看这个

【讨论】:

  • 只有当style 是第一个属性时才有效。如果标签 name 包含 style,它也将不起作用。
  • &lt;\s 不是有效的 html 标记。
【解决方案2】:

如果你喜欢正则表达式,这对我有用。 (注意 - 不包括过滤掉 cmets、doctype 和其他实体。
其他警告;标签可以嵌入到脚本、cmets 和其他东西中。)

span 标记(w/ attr)没有术语|范围属性

'<span
  (?=\s)
  (?! (?:[^>"\']|(?>".*?"|\'.*?\'))*? (?<=\s) (?:term|range) \s*= )
  \s+ (?:".*?"|\'.*?\'|[^>]*?)+ 
>'

任何标签(w/ attr)无术语|范围属性

'<[A-Za-z_:][\w:.-]*
  (?=\s)
  (?! (?:[^>"\']|(?>".*?"|\'.*?\'))*? (?<=\s) (?:term|range) \s*= )
  \s+ (?:".*?"|\'.*?\'|[^>]*?)+ 
>'

任何标签(w/o attr)无术语|范围属性

'<
  (?:
    [A-Za-z_:][\w:.-]*
    (?=\s)
    (?! (?:[^>"\']|(?>".*?"|\'.*?\'))*? (?<=\s) (?:term|range) \s*= )
    \s+ (?:".*?"|\'.*?\'|[^>]*?)+ 
  |
    /?[A-Za-z_:][\w:.-]*\s*/?
  )
>'

更新

使用 (?>) 构造的替代方法
下面的正则表达式用于无-'term|range'-属性
标志 = (g)global 和 (s)dotall

span 标签带属性
链接:http://regexr.com?2vrjr
正则表达式:&lt;span(?=\s)(?!(?:[^&gt;"\']|"[^"]*"|\'[^\']*\')*?(?&lt;=\s)(?:term|range)\s*=)(?!\s*/?&gt;)\s+(?:".*?"|\'.*?\'|[^&gt;]*?)+&gt;

任何带有属性的标签
链接:http://regexr.com?2vrju
正则表达式:&lt;[A-Za-z_:][\w:.-]*(?=\s)(?!(?:[^&gt;"\']|"[^"]*"|\'[^\']*\')*?(?&lt;=\s)(?:term|range)\s*=)(?!\s*/?&gt;)\s+(?:".*?"|\'.*?\'|[^&gt;]*?)+&gt;

任何带有 attr 或 wo/attr 的标签
链接:http://regexr.com?2vrk1
正则表达式:&lt;(?:[A-Za-z_:][\w:.-]*(?=\s)(?!(?:[^&gt;"\']|"[^"]*"|\'[^\']*\')*?(?&lt;=\s)(?:term|range)\s*=)(?!\s*/?&gt;)\s+(?:".*?"|\'.*?\'|[^&gt;]*?)+|/?[A-Za-z_:][\w:.-]*\s*/?)&gt;

'匹配每个标签,除了那些有 term="occasionally"'的标签之外

链接:http://regexr.com?2vrka
&lt;(?:[A-Za-z_:][\w:.-]*(?=\s)(?!(?:[^&gt;"\']|"[^"]*"|\'[^\']*\')*?(?&lt;=\s)term\s*=\s*(["'])\s*occasionally\s*\1)(?!\s*/?&gt;)\s+(?:".*?"|\'.*?\'|[^&gt;]*?)+|/?[A-Za-z_:][\w:.-]*\s*/?)&gt;

【讨论】:

  • 嗨,我在这个示例中尝试了你的正则表达式regexr.com?2vrg3 请看看。它似乎不匹配。例如,尝试匹配每个标签,除了那些有 term="occasionalally" 的标签。这应该给你我想要达到的目标的印象。我还没有解决这个问题,我写的正则表达式接近预期的结果,但是如果除了 term 和 range 之外还有另一个属性,它就会失败。谢谢
  • @user253530 - 3 个问题; 1.你在正则表达式中留了空格,2.flag dotall 没有设置,3.这个引擎不喜欢所有格形式(?&gt;exp)。在我的更新中添加了替代正则表达式和链接。
【解决方案3】:

这会做你想做的事。它是为 Perl 程序编写的,格式可能因您使用的语言而异

/(?! [^>]+ \b(?:item|range)= ) (<[a-z]+.*?>) /igx

下面的代码在 Perl 程序中演示了这种模式

use strict;
use warnings;

my $pattern = qr/ (?! [^>]+ \b(?:item|range)= ) (<[a-z]+.*?>) /ix;

my $str = <<'END';

<span class="inline prewrap strong">DATE:</span>    12/01/10
<span class="inline prewrap strong">MR:</span>  1234567
<span class="inline prewrap strong">DOB:</span> 12/01/65
<span class="inline prewrap strong">HISTORY OF PRESENT ILLNESS:</span>  Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum

<span class="inline prewrap strong">MEDICATIONS:</span>  <span term="Advil" range="true">Advil </span>and Ibuprofen.

END

print "$_\n" foreach $str =~ /$pattern/g;

输出

<span class="inline prewrap strong">
<span class="inline prewrap strong">
<span class="inline prewrap strong">
<span class="inline prewrap strong">
<span class="inline prewrap strong">

【讨论】:

  • 这不是我想要的输出 :) 想象一下,如果我用这些结果进行替换......我将有 到处都是。我解决了自己的问题,花了一些时间,但我做到了。斜体或大写字母,这只是一个感知问题。我个人喜欢大写字母,因为它们很突出。有些人对它们更敏感......由于我们在这里没有使用语音,我认为你将我的大写字母解释为提高音调的标志有点过分了。但是,嘿,我们都生活在我们的小数字世界中……不是吗?
  • 您最初没有提到任何有关使用该模式执行替换的内容。请在此处显示您的解决方案作为答案。
【解决方案4】:
<\w+\s+(?!term).*?>(.*?)</.*?>

【讨论】:

  • 不允许&lt;tag attribute1="value" term="text"&gt;
  • 也没有,我正在创建 所以我确切地知道我在寻找什么。 “术语”属性不可能有另一个属性。
【解决方案5】:

我认为你应该使用 HTML 解析器来解决这个问题。创建自己的正则表达式是可能的,但肯定是错误的。想象一下你的代码包含这样的表达式

< span      class = "a"              >b< / span         >

这也是有效的,但要考虑正则表达式中所有可能的空格和 TAB 字符并不容易,并且需要进行测试才能确保它按预期工作。

【讨论】:

  • 我认为在这种情况下,在涉及 XML 时避免正则表达式的下意识反应是不合适的。单个标签是定义明确的项目,除了出现在评论中的标签外,可以通过正则表达式轻松找到。
  • ]*?class[\s]*?=\s*([\'\"\s])(.*?)\1 [^>]*?> 如果您正在寻找特定标签,则可以绕过最有效的 html -> 类第 2 组将匹配您的类名,第 1 组将作为分隔符('、"、空格)例如,所有这些:regexr.com?34l34
猜你喜欢
  • 1970-01-01
  • 2023-03-24
  • 2013-06-16
  • 2019-10-09
  • 2019-04-12
  • 1970-01-01
  • 2015-03-15
  • 1970-01-01
  • 2011-04-12
相关资源
最近更新 更多