【问题标题】:REGEX to match starting and ending span tags without their inner text正则表达式匹配没有其内部文本的开始和结束跨度标签
【发布时间】:2012-01-17 01:43:05
【问题描述】:

我正在使用以下正则表达式来替换字符串:

<\/?(span)\b(?:\s+class="highlight")?>

但是这个正则表达式有一个缺陷......以这个示例代码为例:

<p>
   Some text here
   <span class="highlight">This is highlighted</span>
   <span>This is not highlighted</span>
</p>

我的正则表达式将匹配两个跨度标签,尽管我只想要一个设置了 class="highlight" 的标签。如何使用 RegEx 实现这一目标?

PS:请不要告诉我我不应该为此使用 RegEx,因为我会降低你的答案,因为它是题外话。这是 RegEx 人的问题。

编辑:根据下面接受的答案,我正在使用以下正则表达式进行替换 注意:代码在 javascript (mootools) 中

var regex = new RegExp("(<span[^>]+class\\s*=\\s*(\"|')highlight\\2[^>]*>)(.*?)(</span>)",'g');
var replaced = element.get('html').replace(regex, "$3");
element.set('html', replaced);

上面的正则表达式将这里的一些文本替换为“这里的一些文本”(不带双引号)

【问题讨论】:

  • 您不使用正则表达式来处理 HTML。而且您不会告诉人们不要告诉您这一点,并威胁他们对他们的答案投反对票。
  • 我不想要告诉我不应该使用正则表达式的答案,因为我想要一个带有正则表达式的解决方案,我在询问之前浏览了 stackoverflow,我看到了这样的答案来解决人们想要正则表达式解决方案的问题...所以我必须在某个聪明人来回答诸如“不要使用正则表达式解析 html”之类的问题之前声明,这显然对社区没有任何帮助。因此,如果您没有正则表达式的答案,那么我对您的解决方案不感兴趣。如果你这样做,我会投票并接受你的回答。
  • 对不起,我不同意。一方面,我不认为你问这个问题是为了“帮助社区”,所以这甚至不是一个论点。接下来,正则表达式不是解决您的问题的正确工具,显然您知道这一点。争吵不会改变这个事实。如果你要问这样一个问题,你将不得不面对人们会告诉你这个事实。如果人们停止为 HTML 问题提出具有固有缺陷的正则表达式解决方案,这将对“社区”有更大的帮助,因为只要你坚持足够长的时间,它就可以奏效。
  • (这让我问:为什么除了正则表达式之外还有其他解决方案?)
  • 您还有哪些其他解决方案?

标签: javascript regex mootools


【解决方案1】:

这应该提供最大的灵活性。

(<span[^>]+class\s*=\s*("|')highlight\2[^>]*>)[^<]*(</span>)

更新:

开始和结束标记所需的捕获组是 \1 和 \3。

【讨论】:

  • 通过阅读问题的标题,您应该注意到@user253530 希望捕获span 标签的内部文本,只是开始和结束标签本身。
  • 您可以简单地删除括号。你怎么能匹配结束 标记并完全忽略内容?前瞻不会捕获。
  • 我知道。但是基于@user253530 自己的正则表达式,我们只对开始和结束标签感兴趣。
  • 我发现这很有帮助,非常感谢...是的,您确实预料到我需要标签之间的文本,所以这个答案是一个加分
  • @Aram:如果您可以选择使用像 [^&lt;]* 这样的否定字符类,那么您绝对应该更喜欢它而不是像 .*? 这样的惰性量词。如果文本格式不正确,您希望匹配尝试失败,并且希望它尽快失败。这就是正则表达式因其缓慢而笨拙而闻名的地方:正则表达式可能会立即匹配,但实际上需要永远报告失败。 [^&lt;]* 会比.*? 失败很多很多。
【解决方案2】:

只是为了向您展示替代解决方案不仅是可能的 bot 还 比使用正则表达式更好

$$('span.highlight').each(function (node, idx, Elem) {
    var txt = document.createTextNode(Elem.get('text'));
    node.parentNode.replaceChild(txt, node)
});

看到这个小提琴:http://jsfiddle.net/Tomalak/umgZp/

(这简直是我的荣幸,到目前为止,我对 MooTools 的接触为零。可能有比这更优雅的方法。)

【讨论】:

  • 我做不到,感谢您的帮助,但这是不可能的。我正在 js 中实现荧光笔。文本保持不变,用户输入一堆单词,班级在 dom 中查找它们。除了文本中添加的跨度外,其他任何内容都不应更改。我需要这个正则表达式来删除添加的亮点。我希望现在你明白没有比正则表达式更好的解决方案了。这是最快的方式...因为我不知道用户需要什么以及 dom 在加载之前的外观。
  • 人们说你不应该用正则表达式解析 HTML 的唯一原因是你不知道你应该寻找什么......但我知道。我已经把它放在那里,所以我确切地知道我在寻找什么。
  • 没有。人们之所以说一定不能使用正则表达式解析 HTML,是因为正则表达式无法处理 HTML 的嵌套和可变结构。此外,这个四行代码完全完成了您想要做的事情:它删除了突出显示的跨度。当你说你不能使用它时,我真的不明白,这种说法毫无意义。
  • 很好的答案!谢谢@Tomalak
【解决方案3】:

您显然是在声明 class=highlight 部分是可选的,方法是在捕获它的组前面放置一个 ?

这应该为你做:

var regex = /(?:<span\s+[^>]*?\s*class\s*=\s*('|")(?:\S+\s+)?highlight(?:\s+\S+)?\1[^>]*>|<\/span>/;

这还将包括具有类属性的 SPAN 标记,例如 a b c highlight e f g

另外,如果你想捕获一个带有 匹配 结尾的 SPAN 标记,你可以使用它,并分别访问组 1 和组 3 作为开始和结束标记:

var regex = /(<span\s+[^>]*?\s*class\s*=\s*('|")(?:\S+\s+)?highlight(?:\s+\S+)?\1[^>]*>).*?(<\/span>)/;

【讨论】:

  • (?:xyz) 中的?: 指定可选组。
  • 取出 ?只会匹配正常的跨度,这不是我想要的......
  • 当然不是。 (?:\s+class="highlight")?末尾的问号做到了。
  • 对,但那你为什么说“在前面”? :)
  • 我不明白,因为正则表达式是从左到右读取的......但是,没关系。
猜你喜欢
  • 1970-01-01
  • 2019-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-06
  • 2020-04-03
相关资源
最近更新 更多