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

在两个标签之间选择所有文本的最佳方法是什么-ex: 页面上所有‘ <pre>’标签之间的文本。

456551 次浏览

您可以使用 "<pre>(.*?)</pre>"(用您想要的任何文本替换 pre)并提取第一组(用于指定语言的更具体的指令) ,但是这假设了一个过于简单的概念,即您拥有非常简单和有效的 HTML。

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

您不应该尝试使用正则表达式解析 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();

由于这是一个合适的解析器,它将能够处理嵌套标记等。

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

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

试试这个。

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

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

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

有时候标记会有属性,比如 anchor标记有 href,然后使用下面的模式。

 <[tag][^>]*>(.+?)</[tag]>
<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>

多行:

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

我会用这个。

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

基本上它的作用是:

(?<=(<pre>))选择必须与 <pre>标签预先

这只是我想应用的一个正则表达式。在这种情况下,它选择字母、数字、换行符或方括号中的示例中列出的一些特殊字符。管道字符 |简单地表示“ 或者”。

字符状态选择一个或多个以上的顺序并不重要。问号将默认行为从“贪婪”更改为“不贪婪”。

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

enter image description here

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

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

在这里,我在 SublimeText 中执行了这个搜索,所以我不必在正则表达式中使用修饰符。

Javascript 不支持后视

上面的示例应该可以很好地使用 PHP、 Perl、 Java 等语言。
但是 Javascript 不支持后向查找,所以我们必须忘记使用‘(?))寻找某种变通方法。也许可以像这样简单地从每个选择的结果中去掉前四个字符 Https://stackoverflow.com/questions/11592033/regex-match-text-between-tags

再看看 非捕获括号JAVASCRIPT REGEX 文档

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

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 代码的,所以补充说:

我使用这种方法:

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

排除分隔标记:

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

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

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

结果将在 pre标记中显示

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

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

这个正则表达式将选择标签之间的一切。无论是在新的一行(多行工作。

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

如果指定了 DOTALL 标志,则匹配包括换行符在内的任何字符

#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

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

(?<=>)([\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分钟的开始,祝你好运。

在 Javascript 中,这很简单,它涵盖了属性和多行:

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

为了选择所有文本之间的前标记我更喜欢

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

$match [0]将有包括 < pre > 标记的结果

$match [1]将包含 < pre > 中的所有内容。

DomDocument 不能在需要在搜索标记中获取包含标记详细信息的文本的情况下工作,因为它会去除所有标记,nodeValue & textContent 将只返回没有标记和属性的文本。

(?<=>)[^<]+

用于记事本 + +

>([^<]+)

用于 AutoIt (选项 返回全局匹配的数组)。

或者

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

Https://regex101.com/r/vtmemy/

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]是内容文本,它适用于任何带有类的标记名(不支持嵌套结构)

 test.match(/<pre>(.*?)<\/pre>/g)?.map((a) => a.replace(/<pre>|<\/pre>/g, ""))

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

这个怎么样:

<PRE>(\X*?)<\/PRE>

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

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

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

正则表达式铁路图 :

Group # 1 = tag name

Group # 2 = string attr

Group # 3 = inner 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 中的换行符)

如果将 (.*?)<\/\1 *>改为 ([\s\S]*?)<\/\1 *>,即使所有内容不在同一行中,它也应该与标记的内部 html 相匹配。由于某些原因,我在 Chrome 和 Node 上无法使用它,但是在 JavaScript 的 Regex Engine 上可以使用它:

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>