首页 > 解决方案 > 正则表达式:匹配两个最接近的字符串,它们之间仅出现另一个字符串

问题描述

我想做两行的非贪婪匹配,但只包括它们之间另一行的出现。

让我用 ffprobe 的日志来说明这一点:

[FRAME]
media_type=video
stream_index=1
pict_type=P
coded_picture_number=1
display_picture_number=0
[/FRAME]
[FRAME]
media_type=video
stream_index=1
pict_type=B
coded_picture_number=1
display_picture_number=0
[/FRAME]
[FRAME]
media_type=video
stream_index=1
pict_type=P
coded_picture_number=1
display_picture_number=0
[/FRAME]
[FRAME]
media_type=video
stream_index=1
pict_type=I
coded_picture_number=1
display_picture_number=0
[/FRAME]
[FRAME]
media_type=video
stream_index=1
pict_type=P
coded_picture_number=1
display_picture_number=0
[/FRAME]
[FRAME]
media_type=video
stream_index=1
pict_type=I
coded_picture_number=1
display_picture_number=0
[/FRAME]

该日志由视频帧组成。帧以 [FRAME] 开始,以 [/FRAME] 结束。

我想在下一帧中匹配 pict_type=B 紧跟 pict_type=I 。

显然pict_type=B.*?pict_type=I在这里不起作用,它会匹配 BPI

我试图将 [/FRAME] 的出现限制为仅 1

pict_type=B(.*?[^\[\/FRAME\]]{1})pict_type=I

但它匹配两个 [/FRAME] 只是为了达到 pict_type=I

此外,每个视频都有不同数量的行,所以用 \r\n 重复做一个正则表达式行是没有用的

我做错了什么,我怎么能告诉它在我的两个 pict_type 之间只允许一个 [/FRAME] ?

标签: regex

解决方案


您可以使用匹配打开[FRAME]和关闭的模式,[/FRAME]同时在下一帧中先匹配pict_type=B然后再匹配第二个pict_type=I,而不使用负前瞻跨越这些边界(?!

\[FRAME](?:\R(?!\[/?FRAME]|pict_type).*)*+\Rpict_type=B(?:\R(?!\[/?FRAME]|pict_type).*)*+\R\[/FRAME]\R\[FRAME](?:\R(?!\[/?FRAME]|pict_type).*)*+\Rpict_type=I(?:\R(?!\[/?FRAME]|pict_type).*)*+\R\[/FRAME]

模式匹配:

  • \[FRAME]匹配[FRAME]
  • (?:\R(?!\[/?FRAME]|pict_type).*)*+匹配所有不以[FRAME][/FRAME]pict_type使用所有格量词开头的行 *+
  • \Rpict_type=B匹配换行符和pict_type=B
  • (?:\R(?!\[/?FRAME]|pict_type).*)*+匹配所有不以[FRAME]or开头[/FRAME]的行pict_type
  • \R\[/FRAME]匹配换行符并匹配结束[/FRAME]
  • \R\[FRAME]匹配换行符并匹配第二个[FRAME]
  • (?:\R(?!\[/?FRAME]|pict_type).*)*+匹配所有不以[FRAME]or开头[/FRAME]的行pict_type
  • \Rpict_type=I匹配换行符并匹配pict_type=I
  • (?:\R(?!\[/?FRAME]|pict_type).*)*+匹配所有不以[FRAME]or开头[/FRAME]的行pict_type
  • \R\[/FRAME]匹配换行符并匹配[/FRAME]

正则表达式演示

在此处输入图像描述


推荐阅读