java - 正则表达式中的通配符仅在停用词之前是贪婪的

标签 java regex regex-lookarounds capturing-group

我正在尝试构建一个“简单”的正则表达式(在 Java 中)来匹配如下句子:

I want to cook something
I want to cook something with chicken and cheese
I want to cook something with chicken but without onions
I want to cook something without onions but with chicken and cheese
I want to cook something with candy but without nuts within 30 minutes

在最好的情况下,它也应该匹配: 我想在 30 分钟内做一些有糖果但没有坚果的东西

在这些示例中,我想捕获“包含”成分、“排除”成分和 cooking 过程的最长“持续时间”。正如您所看到的,这 3 个捕获组中的每一个在模式中都是可选的,每个都以一个特定的单词开头(with,(but)?without,within)并且组应该使用通配符匹配直到找到下一个特定关键字.此外,这些成分可以包含多个单词,因此在第二个/第三个示例中,“chicken and cheese”应该与命名的捕获组“included”相匹配。

在最好的情况下,我想写一个类似于这个的模式:

I want to cook something ((with (?<include>.+))|((but )?without (?<exclude>.+))|(within (?<duration>.+) minutes))*

显然这不起作用,因为这些通配符也可以与关键字匹配,因此在第一个关键字匹配后,其他所有内容(包括更多关键字)都将与相应命名捕获组的贪婪通配符匹配。

我尝试使用前瞻,例如这样的事情:

something ((with (?<IncludedIngredients>.*(?=but)))|(but )?without (?<ExcludedIngredients>.+))+

该正则表达式识别 something with chicken but without onions 但不匹配 something with chicken

是否有一个简单的解决方案可以在正则表达式中执行此操作?

附言“简单”的解决方案意味着我不必在一个句子中指定这些关键字的所有可能组合,也不必按照每个组合中使用的关键字数量对它们进行排序。

最佳答案

它可能可以归结为以下结构。

(?m)^I[ ]want[ ]to[ ]cook[ ]something(?=[ ]|$)(?<Order>(?:(?<with>\b(?:but[ ])?with[ ](?:(?!(?:\b(?:but[ ])?with(?:in|out)?\b)).)*)|(?<without>\b(?:but[ ])?without[ ](?:(?!(?:\b(?:but[ ])?with(?:in|out)?\b)).)*)|(?<time>\bwithin[ ](?<duration>.+)[ ]minutes[ ]?)|(?<unknown>(?:(?!(?:\b(?:but[ ])?with(?:in|out)?\b)).)+))*)$

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

展开

 (?m)
 ^ I [ ] want [ ] to [ ] cook [ ] something
 (?= [ ] | $ )
 (?<Order>                      # (1 start)
      (?:
           (?<with>                      # (2 start)
                \b
                (?: but [ ] )?
                with [ ]
                (?:
                     (?!
                          (?:
                               \b
                               (?: but [ ] )?
                               with
                               (?: in | out )?
                               \b
                          )
                     )
                     .
                )*
           )                             # (2 end)
        |  (?<without>                   # (3 start)
                \b
                (?: but [ ] )?
                without [ ]
                (?:
                     (?!
                          (?:
                               \b
                               (?: but [ ] )?
                               with
                               (?: in | out )?
                               \b
                          )
                     )
                     .
                )*
           )                             # (3 end)
        |  (?<time>                      # (4 start)
                \b within [ ]
                (?<duration> .+ )             # (5)
                [ ] minutes [ ]? 
           )                             # (4 end)
        |  (?<unknown>                   # (6 start)
                (?:
                     (?!
                          (?:
                               \b
                               (?: but [ ] )?
                               with
                               (?: in | out )?
                               \b
                          )
                     )
                     .
                )+
           )                             # (6 end)
      )*
 )                             # (1 end)
 $

关于java - 正则表达式中的通配符仅在停用词之前是贪婪的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58846410/

相关文章:

python - 用于提取占位符匹配的正则表达式

java - 我需要一个 JTextArea,它在行的末尾计算该行中的字符数

java - 找到一个数字的真正大幂

java - 单例连接+单例准备语句

regex - Notepad++中特定长度搜索的通配符

java - java中模式的字符串比较

python:如何在findall中使用for循环

regex - 嵌套正则表达式向前和向后看

java - 计算 StdIn 中的行数和字符数

python 正则表达式 向后查找 向前查找