如何使用正则表达式搜索被双引号包围的文本?

7

我有一个字符串,其中包含一些HTML代码,例如:

This is <strong id="c1-id-8">some</strong> <em id="c1-id-9">text</em>

我需要从每个HTML标记中删除id属性,但是我对正则表达式毫无经验,所以我在互联网上搜索并编写了此模式:[\s]+id=\".*\" 不幸的是,这并没有像我期望的那样起作用。实际上,我希望正则表达式能够捕获id="后面跟着任意字符重复任意次数并以最近的双引号终止的内容;在这个例子中,我希望能捕获id="c1-id-8"id="c1-id-9"。 但是相反,该模式返回了子字符串id="c1-id-8">some</strong> <em id="c1-id-9",它找到了id="的第一个出现和最后一个双引号字符的最后一个出现。
请问我的模式有什么问题,如何修复呢? 非常感谢

2
第∞次了,使用解析器。HTML不是一种正则语言。 - Matt Ball
5个回答

13
你的正则表达式中的量词 .* 是贪婪模式(意味着它会尽可能匹配更多字符)。为了匹配最少的必要字符,你可以使用类似这样的表达式 /\s+id=\"[^\"]*\"/。方括号 [] 表示一个字符类,所以它将匹配方括号里面的所有字符。插入符号 [^] 在字符类开头表示否定,意味着它将匹配除括号内指定内容之外的所有字符
另一种方法是通过将 .* 量词更改为 .*? 来使其变为懒惰模式,这将匹配尽可能少的字符。

非常感谢,现在我明白它是如何工作的:(1) 它从搜索任意数量的空格+id="开始 (2) 它搜索任何字符,直到找到双引号字符 (3) 它搜索双引号字符。 - Cesco
1
正确。并且赞扬你在发帖之前去研究了你的问题,这总是有帮助的。 - nachito
@ridgerunner非常好的澄清/更正。我已经编辑了我的答案,希望更准确。 - nachito

4
.*中,星号是贪婪量词,它会尽可能匹配尽可能多的字符,因此它只会在找到最后一个"时停止匹配。
您可以使用".*?"使其变成非贪婪量词,或者(我认为更好的方法)使用"[^"]*"来明确匹配内容:
"      # match a quote
[^"]*  # match any number of characters except quotes
"      # match a quote

如果您是从字符串构建正则表达式,可能仍需要转义引号;否则在正则表达式中引号不是特殊字符,因此不需要转义。


1

grep的示例:(重点是表达式)

kent$  echo 'This is <strong id="c1-id-8">some</strong> <em id="c1-id-9">text</em>'|grep -oP '(?<= id=")[^"]*(?=">)'
c1-id-8
c1-id-9

1

在一般情况下,解析器是最好的解决方案,但编写解析器需要时间。有些情况下,编写解析器所需的时间比解析器节省的时间还要多;也许这就是这种情况。

你想要的是非贪婪匹配或更精确的匹配。/[\s]+id=\".?\"/ 可以解决问题,但 [\s]+id=\"[^"]\" 会更快。

请注意,一个完整的正则表达式,考虑到转义引号字符的可能性,允许单引号而不是双引号,并允许没有引号的情况,将会更加复杂。在那种情况下,你真的需要一个解析器。


0
如果你知道你的id总是7个字符,你可以这样做。
/\sid=".{7}"/g

所以。。

var a = 'This is <strong id="c1-id-8">some</strong> <em id="c1-id-9">text</em>';

var b = a.replace(/\sid=".{7}"/g, '');

document.write(b);

例子:http://jsfiddle.net/jasongennaro/XPMze/

检查检查器以查看已删除的id


非常感谢。不幸的是,ID字符串可能是任意长度,我无法控制它 :-( - Cesco
谁给这个点踩了。我不介意被踩,但你能告诉我为什么吗? - Jason Gennaro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接