正则表达式(。*)没有匹配第二种情况

时间:2016-05-23 17:29:28

标签: regex

给出以下示例输入文本:

  

{{A1 | def | ghi | jkl}}你好世界。 {{A2 | mno}}再见世界。

如何创建正则表达式模式以仅匹配{{ ... }}的第一个实例(即仅{{A1|def|ghi|jkl}})。 A1A2是固定输入,defghijklmno可以是任何内容。

我试过这个:

\{\{A1\|(.*)\|(.*)\|(.*)\}\}

但这会返回所有内容({{A1|def|ghi|jkl}}hello world. {{A2|mno}})。

请注意,defghijklmno可以是数字,英文字母或其他语言(例如中文/日文/韩文)。

2 个答案:

答案 0 :(得分:3)

有点不清楚你想要完成什么。起初,我认为你的问题只是当你真正想要的是A1A2部分时,你得到了整个事情。如果是这样,这就是答案:

由于您未指定使用哪种正则表达式,因此很难确定。如果您使用的是支持环视的版本,您可以执行以下操作:

(?<={{)\w+(?=(\|[^|}]*)+}})

以下是模式的含义:

  • (?<={{) - 这是一个积极的后视表达式,这意味着它断言任何匹配必须以某些字符开头。在这种情况下,字符为{{
  • \w+ - 这是我们匹配的实际部分。在这种情况下,它是一个或多个单词字符。 \w是一个特殊的角色类。但这取决于您使用的正则表达式引擎。 [A-Z][0-9]之类的东西可能更合适,具体取决于您的需求。
  • (?=(\|[^|}]*)+}}) - 这是一个积极的前瞻表达。这意味着它断言任何匹配必须遵循一些特定的字符模式。在这种情况下,它正在寻找匹配(\|[^|}]*)+}}

但是,如果无法环顾四周,那么您可以将其与捕获组匹配,如下所示:

{{(\w+)(\|[^|}]*)+}}

如果您这样做,则需要为每场比赛读取第一组的值。

只要找到第一场比赛,这实际上取决于您使用的工具或语言。大多数正则表达式引擎默认只找到第一个匹配项,并且只在指定了全局修饰符时才找到其他匹配项(最后通常为/g)。

然而,现在,在编辑了你的问题并且更好地理解你的意思之后,我认为你真正的问题是贪婪。正则表达式中的重复(例如*)默认情况下是贪婪的。这意味着他们将捕获尽可能多的文本并仍然匹配。在这种情况下,您不希望它找到最长的匹配。在这种情况下,您希望它找到最短的匹配。你可以简单地通过使重复变得懒惰(即非贪婪)来做到这一点。为此,只需在?之后添加*即可。例如:

\{\{A1\|(.*?)\|(.*?)\|(.*?)\}\}

然而,这不是很有效率。如果要经常使用此模式或在大输入上使用,最好使用限制性更强的字符类,例如[^}|]而不是.,这样就不需要延迟修饰符。例如:

\{\{A1\|([^}|]*)\|([^}|]*)\|([^}|]*)\}\}

或者更简单:

{{A1(\|([^}|]*)){3}}}

答案 1 :(得分:0)

你的模式的问题很简单,你已经让所有*量词都贪婪了。他们尽可能多地匹配字符串(同时仍允许整个模式匹配)。只是让他们不贪婪*?

\{\{A1\|(.*?)\|(.*?)\|(.*?)\}\}

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