停在Regex的第一次出现

时间:2019-10-18 17:20:38

标签: regex

我的文字只包含一个人的详细信息,但包含许多不同的宠物信息。我正在寻找一种使用正则表达式选择仅个人详细信息的方法。

Here is what I've tried

TEXT:

# Person
---
Name: Nick King 
Age: 18
Speech: "Hello!! How are you? Me & you are different. I'm the #1"

# Pet = Dog
---
Name: Bill

# Pet = Cat
---
Name: Zacky

正则表达式:

#\s*Person(\n|.)+(?=#\s*Pet)

由于我使用过 anychar(。)标记,正则表达式始终会捕获到最后一只宠物

我怎样才能停在第一只宠物上?

假定“狗”并不总是列表中的第一个宠物。

2 个答案:

答案 0 :(得分:2)

正则表达式可能不是解决此类问题的最佳方法-您可以使用YAML解释器。

如果您致力于使用正则表达式,则有一个简单的解决方案:不满意。

局部不满意

在原始正则表达式中,您拥有:

#\s*Person(\n|.)+(?=#\s*Pet)

在这种情况下,(\n|.)+在进行Pet前瞻之前要匹配尽可能多的字符

如果您在?之后引入+,以使该组读取(\n|.)+,则在进行前瞻之前,您将得到尽可能少的字符。 / p>

#\s*Person(\n|.)+?(?=#\s*Pet)

Regex101对+?的描述如下:

  

+? 量词-匹配一次和无限次,次数尽可能少,根据需要扩展(延迟)

全球不满

除了操作本地的 ungreedy 开关外,还可以使用 U 标志将量词全局设置为 ungreedy

请注意,这会在全球范围内逆转贪婪,因此,如果您设置 U 标志以及使用+?,您将再次尽可能地匹配 。使用一种解决方案或另一种解决方案。

答案 1 :(得分:2)

您使用的(\n|.)+匹配过多,但效率很低,因为它会在任何字符或换行符之间交替显示。

您可以匹配# Person,然后重复匹配所有不以# Pet开头的行

#\s*Person(?:\r?\n(?!#\s*Pet\b).*)*
  • #\s*Person匹配#个人
  • (?:非捕获组
    • \r?\n换行符
    • (?!#\s*Pet\b).*不以# Pet开头时匹配整行
  • )*关闭组并重复0次以上

Regex demo