【问题标题】:Regex non-greedy OR正则表达式非贪婪或
【发布时间】:2013-11-27 23:11:08
【问题描述】:

假设我有 3 个正则表达式 A、B 和 C。

我需要将 A 和 B 匹配在一起或单独匹配,但始终至少匹配一个。 C 是可选的。

到目前为止,我的组合正则表达式是 A?B?C,但如果 A 和 B 不匹配,它仍然有效。 我试过 A|BC 但是如果 A 匹配,则不会评估 B,我需要评估它。

(?P<param1>\d+)?(?P<param2>+\d+)?(?P<param3>\w+)

有什么想法吗?

【问题讨论】:

  • 您希望它如何区分param1param2?在字符串12345678912345 中,123 应该是什么组?所有字符都匹配所有组,因此它们将被第一个使用。
  • 如果django 标记意味着您在 URL 配置文件中执行此操作,一种简化的方法是让两种不同的模式共享相同的视图 - 一种需要 A 和 B,一种需要 A 或 B。我认为还有其他选择,但我必须查看包含 A 和 B 之间分隔符的实际正则表达式。
  • @OGHaza 如果您仔细观察,两者之间有一个“+”号。
  • @PeterDeGlopper 感谢您的解决方案。如果我找不到一体化解决方案,我将使用它。或者如果 param1 和 param2 都为 None,则从视图内部返回 404
  • @andrei,啊,非常狡猾 ;) 你知道\w+ 也捕获数字。如果您知道 param3 不会以数字开头,那么这并不重要,但如果它可以以数字开头,您将得到不正确的结果。

标签: python regex django


【解决方案1】:

使用正则表达式

(?:A(?:B)?|B)(?:C)?

更新:

如果您只需要使用ABC 中的每一个,请使用

((?:A)?(?:B)?)(?!\1{100})(?:C)?

这不是 100% 正确,但应该涵盖所有可能性的 99.99+%

【讨论】:

  • 您将如何对命名组执行此操作?每个命名组只能定义一次。
  • 哇,这确实有效,但我不知道如何。我认为 (?:) 没有捕获任何值。
【解决方案2】:

您可以匹配三个备选方案:(AB|A|B),但这确实要求您捕获 4 个不同的组;两个用于AB 案例,一个用于AB 案例。您提取捕获组的代码必须考虑到这一点:

(?:(?P<param1_and>\d+)(?P<param2_and>+\d+)|(?P<param1_or>\d+)|(?P<param2_or>+\d+))(?P<param3>\w+)

您必须在捕获的组中查找param1_andparam1_orparam2_andparam2_or

【讨论】:

    【解决方案3】:

    虽然丑陋,但也许这会起作用?

    (?P<possibly_joined_params>\d+\+\d+|\d+|\+\d+)(?P<param3>\w+)?
    

    然后在您看来,尝试在“+”上拆分:

    def someview(request, possibly_joined_params, param3=None):
        param_parts = possibly_joined_params.split('+')
        if len(param_parts) == 1:
            param1 = param_parts[0]
            param2 = ''
        else:
            param1, param2 = param_parts
    

    不过,我不确定这是否比仅使用两种模式来匹配视图的想法更简洁。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-27
      • 2010-10-20
      • 2013-02-15
      • 1970-01-01
      相关资源
      最近更新 更多