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

Regex select all text between tags

提问人:basheps 提问时间:8/24/2011 最后编辑:Amal Kbasheps 更新时间:1/30/2023 访问量:497751

问:

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

正则表达 HTML 解析

评论

2赞 Fredrik Pihl 8/24/2011
最好的方法是使用像“Beautiful Soup”这样的 html 解析器,如果你喜欢 python......
1赞 Daniel O'Hara 8/24/2011
最好的方法是使用 XML/HTML 解析器。
4赞 murgatroid99 8/24/2011
一般来说,使用正则表达式来解析html不是一个好主意:stackoverflow.com/questions/1732348/...
0赞 jdh8 8/20/2017
不要使用正则表达式解析标记之间的文本,因为任意嵌套的标记会使 HTML 变得非常规。匹配标签似乎没问题。/<div>.*?<\/div>/.exec("<div><div></div></div>")
0赞 Vishal Sinha 3/24/2023
<div\s+id=“HEADER”>(.|\n)*?<\/div>$

答:

209赞 PyKing 8/24/2011 #1

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

正如其他评论者所建议的那样,如果你正在做一些复杂的事情,请使用 HTML 解析器。

评论

84赞 capikaw 2/2/2017
这不会选择标签之间的文本,而是包括标签。
3赞 Vishal Kumar Sahu 10/1/2017
您需要使用 () 获取选择
6赞 Felipe Augusto 4/11/2018
对于多行标签:<html_tag>(.+)((\s)+(.+))+<\/html_tag>
4赞 rbsdca 5/6/2018
这仍然具有可见性,因此:如果您在尝试后仍然看到标签,那是因为您正在查看完全匹配而不是 (.*?) 捕获组捕获的内容。听起来很俗气,但我总是认为“括号=一对小偷”,因为除非后面跟着一个as in 或,否则每场比赛都会有两个捕获:1 个用于完整匹配,1 个用于捕获组。每增加一组括号,就会增加一个额外的捕获。您只需要知道如何使用您正在使用的任何语言检索这两个捕获。<pre><pre>(.*?)<\/pre>(?(?:(?>
1赞 phil123456 11/5/2020
你需要逃跑 /
9赞 sg3s 8/24/2011 #2

你不应该尝试用正则表达式解析html,看到这个问题以及结果如何。

简单来说,html 不是一种常规语言,因此您不能使用正则表达式完全解析 is。

话虽如此,当没有嵌套类似的标签时,您可以解析 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 3/14/2017
我只想说我有点不安,这仍然在收集反对票,而它是唯一在正则表达式旁边提供适当解决方案的答案,我还添加了充分的警告,这可能不是正确的方式......请至少评论一下我的回答有什么问题。
1赞 trincot 1/27/2019
该问题未标记为 。不知道PHP是怎么来的......php
0赞 sg3s 1/27/2019
@trincot 这是7年多前的事了,所以我不记得了。无论如何,这是使用正则表达式和解析器解决问题的一个例子。正则表达式很好,php 正是我当时所熟知的。
0赞 trincot 1/27/2019
我明白了,我看到了你的第一条评论,并认为这可以解释一些反对票。
0赞 CS QGB 7/8/2021
“/<([\w]+)[^>]*>(.*?)python 中的 <\/\1>/“ 不匹配
195赞 zac 6/2/2013 #3

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

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

评论

9赞 Caleuanhopkins 12/1/2015
在处理多行 HTML 标签时添加的重要一点。仅当 HTML 标记在同一行上时,所选答案才有效。(.|\n)*?
7赞 Mark 7/20/2017
<PRE>(.|\n|\r\n)*?<\/PRE> 用于 Windows 行尾
7赞 Wiktor Stribiżew 10/21/2018
永远不要用于匹配任何字符。始终与(单行)修饰符一起使用。或者一种解决方法。(.|\n)*?.s[\s\S]*?
0赞 wkille 2/27/2020
我想在记事本++中选择代码注释,所以使用这个答案,我想出了完成这项工作的答案 - 谢谢/\*(.|\n)*?\*/
5赞 Heriberto Rivera 10/24/2015 #4

试试这个....

(?<=\<any_tag\>)(\s*.*\s*)(?=\<\/any_tag\>)

评论

3赞 allicarn 9/24/2016
请注意,JavaScript 不支持向后看。
0赞 Heriberto Rivera 4/2/2017
当然是噢,但这个正则表达式是针对 Java 的。感谢您的留言。
25赞 Shravan Ramamurthy 11/12/2015 #5

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

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

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

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

评论

0赞 Alex Byrth 2/26/2016
尝试第一个示例为 '<head>(.+?)</头>“,并按预期工作。但是第二个我没有结果。
1赞 Martin Schneider 9/14/2016
这是行不通的。 将匹配 ,并且<[tag]><t><a><g>
8赞 LWC 7/7/2018
@MA-Maddin - 我想你错过了这个部分。Replace [tag] with the actual element you wish to extract the content from
4赞 Martin Schneider 7/7/2018
哦,好吧,是的。这些应该被完全省略。这会更清楚,因为它们在正则表达式中的含义以及人们先扫描代码后阅读文本的事实;)[]
-4赞 user5988518 2/27/2016 #6
<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 2/27/2016
请用文字介绍/解释您的答案。
-1赞 Dilip 11/17/2016 #7

对于多行:

<htmltag>(.+)((\s)+(.+))+</htmltag>
42赞 DevWL 12/1/2016 #8

这就是我会用的。

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

基本上它的作用是:

(?<=(<pre>))选择必须在前面加上标签<pre>

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

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

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

enter image description here

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

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

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

Javascript 不支持 lookbehind

上面的例子应该可以很好地与PHP,Perl,Java等语言一起使用。
然而,Javascript 不支持 lookback,所以我们不得不忘记使用'(?))“并寻找某种解决方法。也许简单地从每个选择的结果中剥离前四个字符,就像这里一样 https://stackoverflow.com/questions/11592033/regex-match-text-between-tags

另请参阅 JAVASCRIPT REGEX DOCUMENTATION 了解非捕获括号

评论

0赞 David Zwart 9/14/2018
请注意,您需要用 ' 转义单引号/双引号字符,以便将正则表达式放在字符串中。
0赞 Ammy 2/17/2017 #9

你可以使用Pattern pattern = Pattern.compile( "[^<'tagname'/>]" );

2赞 Shishir Arora 8/28/2017 #10

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赞 T.Todua 11/29/2017 #11

我使用这个解决方案:

preg_match_all( '/<((?!<)(.|\n))*?\>/si',  $content, $new);
var_dump($new);
51赞 Jean-Simon Collard 7/5/2018 #12

要排除分隔标记,请执行以下操作:

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

(?<=<pre>)在之后查找文本<pre>

(?=</pre>)查找之前的文本</pre>

结果将在标签内文本pre

评论

0赞 KingKongCoder 9/16/2019
使用此方法的人会查看 @krishna thakor 的答案,该答案还可以考虑内容在标签之间是否有新行
0赞 Pking 5/10/2020
这在我的情况下有所帮助(不需要考虑换行符)。谢谢。
2赞 Evan Kleiner 9/16/2022
如果您有多个元素,则此操作不起作用。例如,<pre>first</pre><pre>second</pre>
12赞 maqduni 8/30/2018 #13

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

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

评论

2赞 Cody 2/14/2022
谢谢。在对我有用之前,我烧掉了上述所有内容。需要一个来抓取 SCSS 和 HTML 文件 - innerHTML 的 - 这成功了。这里是:regex101.com/r/VqhNsI/1style[lang="scss"]
1赞 kiwichris 8/17/2022
只有一个对我有用(JavaScript)
2赞 Krishna thakor 10/16/2018 #14

preg_match_all(/<pre>([^>]*?)<\/pre>/,$content,$matches)此正则表达式将选择 everyting between 标签。不管是在新行中(使用多行。

2赞 John 10/17/2019 #15

在 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赞 Just Me 4/4/2022
非常好的 Python 代码,谢谢
26赞 Clarius 12/23/2019 #16

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

(?<=>)([\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 '</'

screen capture from regex101.com

我希望这能成为 10 的开始。运气。

评论

4赞 Sean Feldman 1/6/2020
谢谢。这不仅是一个更好的答案,而且还是 regex101 网站的绝佳链接。点赞!🙂
0赞 Raphael Setin 8/21/2021
上面的正则表达式非常出色,但它只会返回找到的第一个匹配项,并且不会涵盖特殊字符或新行。为此,请改用以下命令:{}[]:“;'?,.\/]+)(?=<\/)/gm);'。这将返回一个包含所有匹配项的数组,包括几乎所有可用的特殊字符。myString.match(/(?<=>)([\w\s\-\!@#$%^&*()_+|~=
0赞 Vijayakumar 11/21/2022
@RaphaelSetin 我们可以拥有 (?<=>)([^>]*)(?=<\/) ,而不是为单词和特殊字符设置大的正则表达式组合,这将匹配文本中的所有单词、空格和特殊字符
0赞 Raphael Setin 11/22/2022
@Vijayakumar我不是正则表达式的专家,这就是为什么我提出的解决方案不是那么花哨哈哈。如果您的解决方案有效,那就更好了。但在我看来需要注意的是,我不知道你的具体涵盖了哪些特殊字符。你至少应该提到它们。
-1赞 Jonathan 5/16/2020 #17

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

/<pre[^>]*>([\s\S]*?)<\/pre>/
1赞 nirvana74v 3/31/2021 #18

要选择我更喜欢的预标记之间的所有文本

preg_match('#<pre>([\w\W\s]*)</pre>#',$str,$matches);

$matches[0] 将包含包含<pre>标签的结果

$matches[1] 将包含所有内容 <pre>。

DomDocument 在要求在搜索的标签中获取带有标签详细信息的文本的情况下无法工作,因为它会剥离所有标签,nodeValue 和 textContent 将仅返回没有标签和属性的文本。

2赞 aptyp 5/7/2021 #19
(?<=>)[^<]+

对于记事本++

>([^<]+)

for AutoIt(选项 Return array of global matchs)。

 (?=>([^<]+))

https://regex101.com/r/VtmEmY/1

0赞 coosigma 7/16/2021 #20
const content = '<p class="title responsive">ABC</p>';
const blog = {content};
const re = /<([^> ]+)([^>]*)>([^<]+)(<\/\1>)/;
const matches = content.match(re);
console.log(matches[3]);

matches[3]是内容文本,这适用于任何带有类的标记名称。(不支持嵌套结构)

1赞 Hamzat Oluwabori 7/29/2022 #21
 test.match(/<pre>(.*?)<\/pre>/g)?.map((a) => a.replace(/<pre>|<\/pre>/g, ""))

这应该是首选解决方案。特别是当您在上下文中有多个 pre 标记时

0赞 James Gardiner 10/18/2022 #22

怎么样:

<PRE>(\X*?)<\/PRE>
1赞 axell-brendow 11/13/2022 #23

PyKing 的答案更复杂,但匹配任何类型的标签(自闭合除外),并考虑标签具有类似 HTML 的字符串属性的情况。

/<TAG_NAME(?:STRING|NOT_CLOSING_TAG_NOT_QUOTE)+>INNER_HTML<\/\1 *>/g

生:/<([^\s</>]+)(?:("(?:[^"\\]|\\.)*")|[^>"])+>(.*?)<\/\1 *>/g

正则表达式铁路图

组 #1 = 标签名称

组 #2 = 字符串 attr

组 #3 = 内部 HTML

Regex Railroad diagram

JavaScript 代码测试:

let TAG_NAME = '([^\s</>]+)';
let NOT_CLOSING_TAG_NOT_QUOTE = '[^>"]';
let STRING = '("(?:[^"\\\\]|\\\\.)*")';

let NON_SELF_CLOSING_HTML_TAG =
                                                              // \1 is a back reference to TAG_NAME
    `<${TAG_NAME}(?:${STRING}|${NOT_CLOSING_TAG_NOT_QUOTE})+>(.*?)</\\1 *>`;

let tagRegex = new RegExp(NON_SELF_CLOSING_HTML_TAG, 'g');

let myStr = `Aenean <abc href="/life<><>\\"<?/abc></abc>"><a>life</a></abc> sed consectetur.
<a href="/work">Work Inner HTML</a> quis risus eget <a href="/about">about inner html</a> leo.
interacted with any of the <<<ve text="<></ve>>">abc</ve>`;

let matches = myStr.match(tagRegex);

// Removing 'g' flag to match each tag part in the for loop
tagRegex = new RegExp(NON_SELF_CLOSING_HTML_TAG);

for (let i = 0; i < matches.length; i++) {
  let tagParts = matches[i].match(tagRegex);
  console.log(`Tag #${i} = [${tagParts[0]}]`);
  console.log(`Tag #${i} name: [${tagParts[1]}]`);
  console.log(`Tag #${i} string attr: [${tagParts[2]}]`);
  console.log(`Tag #${i} inner html: [${tagParts[3]}]`);
  console.log('');
}

输出:

Tag #0 = [<abc href="/life<><>\"<?/abc></abc>"><a>life</a></abc>]
Tag #0 name: [abc]
Tag #0 string attr: ["/life<><>\"<?/abc></abc>"]
Tag #0 inner html: [<a>life</a>]

Tag #1 = [<a href="/work">Work Inner HTML</a>]
Tag #1 name: [a]
Tag #1 string attr: ["/work"]
Tag #1 inner html: [Work Inner HTML]

Tag #2 = [<a href="/about">about inner html</a>]
Tag #2 name: [a]
Tag #2 string attr: ["/about"]
Tag #2 inner html: [about inner html]

Tag #3 = [<ve text="<></ve>>">abc</ve>]
Tag #3 name: [ve]
Tag #3 string attr: ["<></ve>>"]
Tag #3 inner html: [abc]

如果出现以下情况,则此操作不起作用:

  • 该标记具有相同类型的任何后代标记
  • 标记以一行开头,以另一行结束。(就我而言,我 从 HTML 中删除换行符)

如果您更改为它,即使所有内容都不在同一行中,它也应该与标签的内部 html 匹配。出于某种原因,它在 Chrome 和 Node 上对我不起作用,但在这里与 JavaScript 的正则表达式引擎一起工作:(.*?)<\/\1 *>([\s\S]*?)<\/\1 *>

https://www.regextester.com

正则表达式:<([^\s</>]+)(?:("(?:[^"\\]|\\.)*")|[^>"])+>([\s\S]*?)<\/\1 *>

测试字符串:

Aenean lacinia <abc href="/life<><><?/a></a>">  
<a>life</a></abc> sed consectetur.
<a href="/work">Work</a> quis risus eget urna mollis ornare <a href="/about">about</a> leo.
interacted with any of the <<<ve text="<></ve>>">abc</ve>