【问题标题】:How to exclude one set of words but include another in qregexp?如何在 qregexp 中排除一组单词但包含另一组单词?
【发布时间】:2015-08-15 15:28:28
【问题描述】:

我正在尝试排除一组单词,但在 qregexp 表达式中包含另一组单词,但我目前无法解决这个问题。

这是我尝试过的一些事情(这个例子包括了所有的单词):

(words|I|want|to|include)(?!the|ones|that|should|not|match)

所以我尝试了这个(没有返回任何结果):

^(words|I|want|to|include)(?:(?!the|ones|that|should|not|match).)*$

我错过了什么吗?

编辑:我需要这样一个不寻常的正则表达式(包括/排除)的原因是因为我想搜索一系列文章并过滤其中包含包含单词的文章,但如果它们也包含排除单词则不过滤在他们里面。

例如,如果文章 A 是:

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

B 条是:

Vivamus fermentum semper porta.

然后,包含 lorem 的正则表达式将过滤文章 A 而不是 B。但如果 ipsum 是我要排除的单词,我不希望文章 A 被过滤。

我考虑做一个正则表达式来过滤出我想要的单词的文章,然后运行第二个正则表达式,排除第一组我不想要的文章,但不幸的是我使用的软件不允许我这样做这。我只能运行一个正则表达式。

【问题讨论】:

  • 这没有意义。您正在明确枚举要匹配的单词(“包含”)。之后无需“排除”任何内容;您已经知道白名单上的内容了。
  • 包含是什么意思?列表中至少有一个词?
  • 我使用这个 RSS 软件 (QuiteRSS),它允许我使用 qregexp 过滤掉包含某些单词的文章。但是,如果否定前瞻中的单词也在文章中,我不希望包含这些单词的文章被过滤掉。
  • 所有答案都是一样的。

标签: regex qregexp


【解决方案1】:

我认为没有必要使用温和的贪婪量词。在锚定的否定预测中使用排除的词作为替代词。让我来指导你。

您说,您有Lorem ipsum dolor sit amet, consectetur adipiscing elit.,并且您希望它匹配,因为它包含单词lorem。正则表达式是\\blorem\\b(QRegExp.CaseInsensitive 设置为1),其中\b 用于强制整个单词匹配。如果字符串包含单词ipsum,为了防止匹配,您需要在字符串的最开始使用前瞻。

^(?!.*\\bipsum\\b).*\\blorem\\b

现在,it does not match the string in question。

要添加更多替代方案,我们可以使用alternation operator |,我们可以这样做:^(?!.*\\b(?:words|to|exclude)\\b).*\\b(?:words|to|include)\\b。请注意non-capturing groups 的使用,它不存储任何捕获的文本,与将匹配文本保存在缓冲区中的捕获组相比,它可能会提高性能。

因此,你得到

^(?!.*\\b(?:the|ones|that|should|not|match)\\b).*\\b(?:words|I|want|to|include)\\b

见demo

两个备注:

  1. 在演示网站上,必须使用单反斜杠,我在这里将它们加倍以用于QRegExp。
  2. 在 Qt 中,模式中的 . 匹配任何字符,包括换行符。在演示网站上,点与换行符不匹配。如果您需要相同的功能,您可能希望将其替换为 [^\n],但我认为没有必要。

【讨论】:

    【解决方案2】:
    ^(?:(?!\b(?:the|ones|that|should|not|match)\b).)*\b(?:words|I|want|to|include)\b(?:(?!\b(?:the|ones|that|should|not|match)\b).)*$
    

    在找到应该匹配的单词后,您需要为这两个部分添加前瞻。参见演示。

    https://regex101.com/r/bK9wF1/3

    或

    ^(?!.*\b(?:the|ones|that|should|not|match)\b)(?=.*\b(?:words|I|want|to|include)\b).*$
    

    在lookaheads下添加两个条件。查看演示。

    https://regex101.com/r/uF4oY4/60

    【讨论】:

      【解决方案3】:

      你离得很近。原因

      ^(words|I|want|to|include)(?:(?!the|ones|that|should|not|match).)*$
      

      不起作用是因为它意味着 开始 用我想要包含的单词之一并继续直到结束的事情,这不是其中之一我不想包括的话。要修复它,您可以简单地将开始检查更改为使用正向预测:

      ^(?=.*(?:words|I|want|to|include))(?:(?!the|ones|that|should|not|match).)*$
      

      现在这意味着确保从一开始直到某个点,至少有一个我想要包含的词并且然后像原来的正则表达式一样继续。

      为了更严格,你可以使用word boundaries:

      ^(?=.*\b(?:words|I|want|to|include)\b)(?:(?!\b(?:the|ones|that|should|not|match)\b).)*$
      

      注意这些都区分大小写。要改变它,你可以使用QRegExp::setCaseSensitivity

      【讨论】:

        【解决方案4】:

        试试这个:

        ^(?:(?:(?!\b(?:the|ones|that|should|not|match)\b).|))*?\b(?:words|I|want|to|include)\b(?:(?:(?!\b(?:the|ones|that|should|not|match)\b).|))*$
        

        参见Debuggex Demo(带有匹配和不匹配示例)。

        注意:以上假设 QRegExp 支持可变长度前瞻 - 我尚未验证这一点。

        说明:

        1. 所有单词都必须准确(例如,包括“word”,但不包括“sword”或“words”),因此两边都包含在 \b 中。
        2. 对于您想要包含的单词,只有至少一个出现至少一次才重要 - 这就是要搜索的全部内容。
        3. 排除列表中的任何单词都可能出现在之前或之后搜索的单词,因此需要一个“排除组”两侧。
        4. 排除组是使用this answer 中很好解释的方法实现的。
        5. 第一个排除组使用*? 使其不贪婪,因此它不会消耗整个文本并在找到搜索词后立即停止。
        6. 正则表达式包含在^...$ 中,以确保检查/匹配整个字符串,而不仅仅是其中的一部分。
        7. 在第一个括号后立即使用?: 将所有组标记为非捕获组。
        8. 匹配应该不区分大小写,因此正则表达式应该有适当的标志来执行此操作(例如 /i)。

        【讨论】:

          【解决方案5】:

          您似乎需要的简化版本:

          ^(?:(?!ipsum).)*(?:lorem)(?:(?!ipsum).)*$

          Formatted:

          ^                    # BOS
           (?:
                (?! ipsum )          # Preceding text, but not these words
                . 
           )*
           (?: lorem )          # Text wanted
           (?:
                (?! ipsum )          # Following text, but not these words
                . 
           )*
           $                    # EOS
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-07-26
            • 2016-03-21
            • 2015-06-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多