【问题标题】:regex to extract lookbehind and lookahead from a regex pattern正则表达式从正则表达式模式中提取lookbehind和lookahead
【发布时间】:2020-02-02 11:12:26
【问题描述】:

我有一个不寻常的应用程序,我需要提取正则表达式模式的后向和前向部分的内容(当然是使用正则表达式!)。例如在以下模式中:

(?<=(?:c|d))123(?=(?:x|y))

匹配以下字符串中的第一个123

abc123xyz123xyz

我需要的是提取以下字符串:

(?:c|d)

(?:x|y)

这很困难,因为我无法轻易找到正确的右括号,因为可能有其他括号,如示例中所示。

只是想知道以前是否有人必须这样做。欢迎任何想法

【问题讨论】:

  • 如果您可以在环视中访问捕获组的值,您可以将非捕获组转换为捕获组并使用字符类来匹配单个字符而不是替代 (?&lt;=([cd]))123(?=([xy])) @987654321 @
  • 想象一个像 (?&lt;=\([abc]\)(?![aeiou])[a-z]\(\))blah(?=[xyz](?:(abc|def)ghi)) 这样的正则表达式,我认为你应该编写一个解析器。
  • 对于 PCRE,(?s)(?&lt;!\\)(?:\\{2})*\K\(\?:(?:[^\\()]|\\.|(\((?:[^()]++|(?1))*\)))*\) 之类的内容会有所帮助。见demo。在 .NET 中,将 (?&lt;!\\)(?:\\{2})*\K 替换为 (?&lt;=(?&lt;!\\)(?:\\{2})*)
  • 第四鸟。谢谢。我可以这样做,但不幸的是,我仍然无法找到正确匹配的右括号。
  • @Kaveh1000,我试图为这个令你困惑的正则表达式提供答案。和我。我不知道++是什么,但现在我清楚了一点,也许它也可以让你更清楚。

标签: regex regex-lookarounds


【解决方案1】:

根据问题的 cmets,我的理解是提问者 Kaveh1000 对 Wiktor 的解决方案感到满意;但是他似乎对那个解决方案的一部分感到困惑

(\((?:[^()]++|(?1))*\))

在这方面,我建议阅读Mastering Regular Expressions, 3rd Edition's,它为这个主题(特别是这个正则表达式)专门写了很多词;我刚刚从那里读到它,在下面我试图表达我的理解:

  1. 它是一个捕获组(…),如果需要,我们可以参考(我们确实在 4.2 中这样做了);
  2. 它匹配一对文字括号和\(…\)之间的东西;
  3. 介于两者之间的东西,(?:…)*,是 0 个或多个(普通贪婪)未捕获表达式的序列;
  4. 这些 0 次或多次重复中的每一个都可以是

    4.1。 0 个或多个非括号的序列,[^()]++

    4.2。或者(?1),它与我们现在匹配的正则表达式匹配(第1点);这就是正则表达式的递归性。

两个音符:

  • 正则表达式(这部分)中出现的文字括号仅通过\(\),它们是有序的(先打开,然后关闭)并且两者都必须匹配;这保证了这部分正则表达式将仅匹配平衡括号。
  • ++ 是必要的,因为如果正则表达式是((something)+)*,则有很多方法可以为+* 分配多个重复,并且所有这些都必须尝试; ++ 而不是+ 会尽可能匹配,因为它在(something)+ 中是单独存在的,只有这样* 才会生效。
  • 但是++ 本身是什么?我的意思是,除了在这个正则表达式中它是必要的原因之外,++ 是什么?与+ 相比,隔离并清楚地看到++ 的效果的一种简单方法是将正则表达式a+aba++ab 与包含aaaaaab 的行进行比较。前者会匹配整行,a+匹配前5个as,ab匹配最后两个字符;后者将不匹配,因为a++ 匹配尽可能多的as 而不会放弃支持正则表达式的其余部分,因此匹配所有6 个a,而不会给ab 留下任何匹配的机会并最终导致匹配失败。

【讨论】:

    猜你喜欢
    • 2021-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-08
    • 2016-04-07
    • 1970-01-01
    相关资源
    最近更新 更多