正则表达式选择标签之间的所有文本


142

在2个标签之间选择所有文本的最佳方法是什么-例如:页面上所有“ pre”标签之间的文本。


2
最好的方法是使用html解析器(例如“ Beautiful Soup”),如果您喜欢python ...
Fredrik Pihl

1
最好的方法是使用XML / HTML解析器。
Daniel O'Hara

4
在一般情况下,使用正则表达式解析HTML是不是一个好主意:stackoverflow.com/questions/1732348/...
murgatroid99

不要使用正则表达式解析标签之间的文本,因为任意嵌套的标签会使HTML变得不规则。匹配标签似乎还可以。 /<div>.*?<\/div>/.exec("<div><div></div></div>")
jdh8

Answers:


156

您可以使用"<pre>(.*?)</pre>",(用所需的任何文本替换pre)并提取第一组(对于更具体的说明,请指定一种语言),但这假设您拥有非常简单且有效的HTML的简单概念。

正如其他评论者所建议的那样,如果您要执行复杂的操作,请使用HTML解析器。


41
这不会在标签之间选择文本,而是包含标签。
capikaw

3
您需要使用()
Sahu V Kumar

2
对于多行标记:<html_tag>(。+)((\ s)+(。+))+ <\ / html_tag>
费利佩·奥古斯托

这样仍然具有可见性:如果<pre>尝试后仍看到标记<pre>(.*?)<\/pre>,那是因为您正在查看完全匹配捕获的内容,而不是(。*?)捕获组。听起来千篇一律,但我始终认为“括号=一双贼”,因为除非(后面是?作为(?:或者(?>,每场比赛将有两个捕获:1,用于捕获组的全场比赛:1。每套附加的括号都会添加一个附加的捕获。您只需要知道如何使用您使用的任何语言来检索两个捕获。
rbsdca

137

标签可以在另一行中完成。这就是为什么\n需要添加的原因。

<PRE>(.|\n)*?<\/PRE>

5
关于(.|\n)*?在多行中处理HTML标签时添加的要点。仅当HTML标记在同一行上时,所选答案才有效。
Caleuanhopkins

3
<PRE>(。| \ n | \ r \ n)*?<\ / PRE>对于Windows行尾
Mark'7

3
永远不要使用(.|\n)*?匹配任何字符。始终.s(单行)修饰符一起使用。或[\s\S]*?解决方法。
WiktorStribiżew18年

我想在notepad ++中选择代码注释,因此我想出了这个答案,用/\*(.|\n)*?\*/它来完成工作–谢谢
wkille

完美答案非常感谢
Omda

25

这就是我会用的。

(?<=(<pre>))(\w|\d|\n|[().,\-:;@#$%^&*\[\]"'+–/\/®°⁰!?{}|`~]| )+?(?=(</pre>))

基本上,它的作用是:

(?<=(<pre>))选择必须在<pre>标签之前

(\w|\d|\n|[().,\-:;@#$%^&*\[\]"'+–/\/®°⁰!?{}|~]| )这只是我要应用的正则表达式。在这种情况下,它将选择字母或数字或换行符或方括号中示例中列出的某些特殊字符。竖线字符|仅表示“ OR ”。

+?加上字符状态以选择上述一项或多项-顺序无关紧要。问号将默认行为从“贪婪”更改为“不贪婪”。

(?=(</pre>))选择必须附加</pre>标签

在此处输入图片说明

根据您的用例,您可能需要添加一些修饰符,例如(im

  • -不区分大小写
  • m-多行搜索

在这里,我在Sublime Text中执行了此搜索,因此不必在正则表达式中使用修饰符。

Javascript不支持向后看

上面的示例可以很好地与PHP,Perl,Java ...等语言配合使用,但是Javascript不支持向后看,因此我们不得不忘记使用(?<=(<pre>))并寻找某种解决方法。也许简单地从每个结果的结果中去除结果的前四个字符,如此处 Regex匹配标记之间的文本

另请参阅JAVASCRIPT REGEX DOCUMENTATION未捕获的括号


请注意,您需要使用`转义单引号/双引号字符,以便将正则表达式放入字符串中。
David Zwart

18

使用以下模式获取元素之间的内容。用[tag]您要从中提取内容的实际元素替换。

<[tag]>(.+?)</[tag]>

有时标签会具有属性,例如anchor标签具有href,然后使用以下模式。

 <[tag][^>]*>(.+?)</[tag]>

尝试第一个示例为“ <head>(。+?)</ head>”,其工作方式与预期的一样。但是第二个我没有结果。
亚历克斯·伯斯'16

1
这行不通。<[tag]>将比赛<t><a><g>
Martin Schneider

2
@ MA-Maddin-我想您错过了这一Replace [tag] with the actual element you wish to extract the content from部分。
LWC '18

2
哦,是的。这些[]应该完全省略。由于它们在RegEx中的含义以及人们首先扫描代码然后阅读文本的事实,这将更加清楚;)
Martin Schneider

14

要排除定界标记:

(?<=<pre>)(.*?)(?=</pre>)

(?<=<pre>) 在寻找文字之后 <pre>

(?=</pre>) 在之前寻找文字 </pre>

结果将在pre标签内发送文字


使用此功能的用户会看到@krishna thakor的答案,该答案还可以考虑内容是否在标签之间有新行
KingKongCoder

就我而言,这很有帮助(无需考虑换行符)。谢谢。

6

您不应该尝试使用正则表达式解析html看到此问题以及结果。

用最简单的术语来说,html不是正则语言,因此不能完全解析正则表达式。

话虽如此,当没有类似的标签嵌套时,您可以解析html的子集。因此,只要介于和之间的任何内容都不是该标签本身,这将起作用:

preg_match("/<([\w]+)[^>]*>(.*?)<\/\1>/", $subject, $matches);
$matches = array ( [0] => full matched string [1] => tag name [2] => tag content )

一个更好的主意是使用一个解析器(例如本机DOMDocument)来加载您的html,然后选择您的标签并获取内部的html,它看起来可能像这样:

$obj = new DOMDocument();
$obj -> load($html);
$obj -> getElementByTagName('el');
$value = $obj -> nodeValue();

并且由于这是一个适当的解析器,它将能够处理嵌套标签等。


2
只是想说,我仍然有点不安,这仍然是人们的不二之选,而这是唯一在正则表达式旁边提供适当解决方案的答案,我还添加了充分的警告,说这可能不是正确的方法...请至少对我的答案有什么问题发表评论。
sg3s

1
该问题未使用标记php。不确定PHP是如何出现的...
trincot

@trincot这已经超过7年了,所以我不记得了。无论如何,这都是使用正则表达式和解析器解决问题的示例。正则表达式很好,而php正是我当时所熟知的。
sg3s

我了解,我看到了您的第一条评论,并认为这可以解释某些不赞成票。
特里科特


4

这似乎是我发现的所有内容中最简单的正则表达式

(?:<TAG>)([\s\S]*)(?:<\/TAG>)
  1. (?:<TAG>)从比赛中排除开始标签
  2. ([\s\S]*)匹配中包括任何空格或非空格字符
  3. (?:<\/TAG>)从比赛中排除结束标记

3

这个答案需要支持环顾四周!这使我能够识别成对的开始和结束标签之间的所有文本。这就是“>”和“ <”之间的所有文本。之所以有效,是因为环顾四周不会消耗与其匹配的字符。

(?<=>)([\ w \ s] +)(?= </)

我使用此HTML片段在https://regex101.com/中对其进行了测试。

<table>
<tr><td>Cell 1</td><td>Cell 2</td><td>Cell 3</td></tr>
<tr><td>Cell 4</td><td>Cell 5</td><td>Cell 6</td></tr>
</table>

这是一个由三个部分组成的游戏:背后的外观,内容和正面的外观。

(?<=>)    # look behind (but don't consume/capture) for a '>'
([\w\s]+) # capture/consume any combination of alpha/numeric/whitespace
(?=<\/)   # look ahead  (but don't consume/capture) for a '</'

regex101.com的屏幕截图

我希望这可以作为10的开始。


谢谢。这不仅是一个更好的答案,而且是到regex101网站的绝佳链接。已投票!🙂
肖恩·费尔德曼

2

var str = "Lorem ipsum <pre>text 1</pre> Lorem ipsum <pre>text 2</pre>";
    str.replace(/<pre>(.*?)<\/pre>/g, function(match, g1) { console.log(g1); });

由于接受的答案没有javascript代码,因此添加以下内容:



1

在Python中,设置DOTALL标志将捕获所有内容,包括换行符。

如果指定了DOTALL标志,则它匹配包括换行符在内的任何字符。docs.python.org

#example.py using Python 3.7.4  
import re

str="""Everything is awesome! <pre>Hello,
World!
    </pre>
"""

# Normally (.*) will not capture newlines, but here re.DOTATLL is set 
pattern = re.compile(r"<pre>(.*)</pre>",re.DOTALL)
matches = pattern.search(str)

print(matches.group(1))

python example.py

Hello,
World!

在文档中所有开始和结束标签之间捕获文本

捕获文档中所有开始和结束标签之间的文本finditer很有用。在下面的示例中,<pre>字符串中存在三个打开和关闭标签。

#example2.py using Python 3.7.4
import re

# str contains three <pre>...</pre> tags
str = """In two different ex-
periments, the authors had subjects chat and solve the <pre>Desert Survival Problem</pre> with a
humorous or non-humorous computer. In both experiments the computer made pre-
programmed comments, but in study 1 subjects were led to believe they were interact-
ing with another person. In the <pre>humor conditions</pre> subjects received a number of funny
comments, for instance: “The mirror is probably too small to be used as a signaling
device to alert rescue teams to your location. Rank it lower. (On the other hand, it
offers <pre>endless opportunity for self-reflection</pre>)”."""

# Normally (.*) will not capture newlines, but here re.DOTATLL is set
# The question mark in (.*?) indicates non greedy matching.
pattern = re.compile(r"<pre>(.*?)</pre>",re.DOTALL)

matches = pattern.finditer(str)


for i,match in enumerate(matches):
    print(f"tag {i}: ",match.group(1))

python example2.py

tag 0:  Desert Survival Problem
tag 1:  humor conditions
tag 2:  endless opportunity for self-reflection

0

对于多行:

<htmltag>(.+)((\s)+(.+))+</htmltag>


0

我使用以下解决方案:

preg_match_all( '/<((?!<)(.|\n))*?\>/si',  $content, $new);
var_dump($new);

-1

在Javascript(以及其他)中,这很简单。它涵盖属性和多行:

/<pre[^>]*>([\s\S]*?)<\/pre>/

-4
<pre>([\r\n\s]*(?!<\w+.*[\/]*>).*[\r\n\s]*|\s*[\r\n\s]*)<code\s+(?:class="(\w+|\w+\s*.+)")>(((?!<\/code>)[\s\S])*)<\/code>[\r\n\s]*((?!<\w+.*[\/]*>).*|\s*)[\r\n\s]*<\/pre>

6
请用文字介绍/解释您的答案。
Andrew Regan
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.