【问题标题】:Regex for `x...(a and b)...y` within a limited length?`x...(a and b)...y` 在有限长度内的正则表达式?
【发布时间】:2021-11-02 16:23:14
【问题描述】:

是否可以在n 的有限长度内指定匹配x...(a and b)...y 的正则表达式?

更准确地说:

  1. 匹配的xy之间的字符长度最多为n
  2. 在匹配的xy 之间必须同时存在ab(不考虑顺序)。
  3. xaby 这里可以代表多字符字符串 sn-p。

测试用例(假设n = 10):

Match:
...x..a...b..y...
...x..b...a..y...
...x..a...b..y...a...
...x..a...b..y...b...
...x..a...b..y...y...
...x..a.x.b..y...
...x..a.y.b..y...
...xaabbaabbay...
...x..a...b..y... ...x..a...b..y... (2 matches)
...xaby...xaby... (2 matches)

Don't match:
...x..a...b......
...x......b..y...
...x..a......y...
...x..a...b......y...
...x......b..y...a...
...x..a......y...b...
...x..a.y.b......
...x..a.y.b......y...
...x..a.y.b.x....y...
.a.x......b..y...
.b.x..a......y...

P.S: 我知道这可以通过简单地匹配/x.{0,n}y/ 来完成,然后检查ab 是否都存在于许多编程语言的匹配字符串中。但是,此问题明确要求单一正则表达式方法,以便它可以在某些应用程序中用作查询,例如 Google Doc 和 Notepad++。

【问题讨论】:

  • 是的,这是可能的(所有长度有限的模式都可以),但会很麻烦。可以使用前瞻吗?
  • 我可以。你可以为这个问题制作一个有效的正则表达式吗?
  • 请添加正则表达式应匹配 x...a.y.b...y 到您的问题。而且它不应该 f.ex。匹配x...a.y.b..1234567890..y,这与第一个要求一起变得更加棘手。
  • @Thefourthbird 是的
  • @Thefourthbird 这也匹配 ...x...a.yx.b...y... 但不应该

标签: regex notepad++


【解决方案1】:

相信你可以使用

x(?:(?(1)(?!)|(a))|(?(2)(?!)|(b))|.){0,10}?y(?(1)|(?!))(?(2)|(?!))

请参阅regex demo详情

  • x - 左侧分隔符
  • (?:(?(1)(?!)|(a))|(?(2)(?!)|(b))|.){0,10}? - 零到十次出现(但尽可能少)
    • (?(1)(?!)|(a)) - 如果 Group 1 为 null(如果 Group 1 之前没有匹配)匹配 a,否则无法立即触发回溯
    • | - 或
    • (?(2)(?!)|(b)) - 如果 Group 2 为 null(如果 Group 2 之前没有匹配)匹配 b,否则无法立即触发回溯
    • |. - 或任何一个字符(默认换行字符除外)
  • y - 右手定界符
  • (?(1)|(?!)) - 条件构造:如果第 1 组参加了比赛(如果第 1 组的值不为空),则继续,否则,比赛失败
  • (?(2)|(?!)) - 条件构造:如果第 2 组参加了比赛(如果第 2 组的值不为空),则继续,否则,比赛失败。

最后两个条件确保匹配的文本中有ab

注意:如果ab 可以是多字符串,n 必须减少到n-(a.length-b.length+2) 的长度。因此,如果aac 并且bbmc,则需要将10 替换为10-(2-3+2) => 7。这也意味着您应该事先检查您的预期限制长度限制,它应该允许 ab 组合的长度。

注意 2:在模式的开头添加 (?s) 以匹配换行符和 .。更多选项请参见How do I match any character across multiple lines in a regular expression?

【讨论】:

  • 谢谢。您提出的解决方案看起来很有希望。不幸的是,这在 ...xaby...xaby... 的情况下失败了,因为没有给出 2 个匹配项。有没有办法修改它以使其适用于这种情况?
  • 使用条件的概念,我已经使用x(?:(?=(?(1)(?!)|(a))|(?(2)(?!)|(b))|).){0,10}?y(?(1)|(?!))(?(2)|(?!)) 让它工作。这将使用前瞻断言作为更智能的方式捕获两个组,并且如果 ab 是多字符,则无需预先修改长度。
  • @DannyLin 我的尝试是x(?:(?(1)(?(2)[^y]|[^b])|(a))|(?(2)(?(1)[^y]|[^a])|(b))|[^xy]){0,10}y(?(1)|(?!))(?(2)|(?!)),但你的更好,只需要非贪婪的重复
  • 为了更简单,稍微修改为x(?:(?=(?(1)|(a))|)(?=(?(2)|(b))|).){0,10}?y(?(1)|(?!))(?(2)|(?!)),并支持ab可能相互重叠的情况(例如a = azb = azz )。
  • @DannyLin 您不需要前瞻。只需从模式消耗部分内的条件句中删除点,并使限制量词变得惰性。我编辑了解决方案。
【解决方案2】:

如果不为xa|b 之间、ab 之间以及a|by 之间的部分生成所有有效的长度组合,我担心这是不可能的。

对于 n=5(即在 xy 之间的 ab 以外的 0-3 个字符:

x ( [^ab]{0} ( a ( [^b]{0} b .{0,3}
                 | [^b]{1} b .{0,2}
                 | [^b]{2} b .{0,1}
                 | [^b]{3} b .{0}   )
             | b ( [^b]{0} a .{0,3}
                 | [^b]{1} a .{0,2}
                 | [^b]{2} a .{0,1}
                 | [^b]{3} a .{0}   ) )
  | [^ab]{1} ( a ( [^b]{0} b .{0,2}
                 | [^b]{1} b .{0,1}
                 | [^b]{2} b .{0}   )
             | b ( [^b]{0} a .{0,2}
                 | [^b]{1} a .{0,1}
                 | [^b]{2} a .{0}   ) )
  | [^ab]{2} ( a ( [^b]{0} b .{0,1}
                 | [^b]{1} b .{0}   )
             | b ( [^b]{0} a .{0,1}
                 | [^b]{1} a .{0}   ) )
  | [^ab]{3} ( a ( [^b]{0} b .{0}   )
             | b ( [^b]{0} a .{0}   ) ) ) y

我使用[^…] 而不是. 来避免从错误的分支回溯太多,尽管它可能会进一步优化。

【讨论】:

  • 我同意制作一个枚举x...a...b...y 长度在n 内的所有组合的正则表达式是可行的。但这可能只能通过编程方式实现,并且在各种有限/罕见的情况下是实用的。
  • @DannyLin 是的。我不认为仅使用高级正则表达式组合器的实用解决方案 - 即使使用环视、条件或递归/子例程。也许我对“有可能”这个问题的理解有点过于字面意思了——你所描述的仍然是一种常规语言。
  • 看来我错了——它可以用条件句来解决。这些我自己还没用过
猜你喜欢
  • 1970-01-01
  • 2014-09-20
  • 2019-11-27
  • 2022-07-21
  • 2013-01-20
  • 1970-01-01
  • 1970-01-01
  • 2012-07-18
  • 1970-01-01
相关资源
最近更新 更多