【问题标题】:Regex with exception of particular words正则表达式,特定单词除外
【发布时间】:2009-12-01 13:00:31
【问题描述】:

我对正则表达式有疑问。 除了一组指定的单词,我需要制作正则表达式,例如:apple、orange、juice。 并且给定这些词,它将匹配除上面那些词之外的所有内容。

applejuice (match)
yummyjuice (match)
yummy-apple-juice (match)
orangeapplejuice (match)
orange-apple-juice (match)
apple-orange-aple (match)
juice-juice-juice (match)
orange-juice (match)

apple (should not match)
orange (should not match)
juice (should not match)

【问题讨论】:

  • 您使用什么语言? “橙汁”也应该匹配,还是失败?
  • 听起来您想将连字符视为单词字符。

标签: regex exception word


【解决方案1】:

如果您真的想使用单个正则表达式执行此操作,您可能会发现环视很有帮助(尤其是本示例中的负前瞻)。为 Ruby 编写的正则表达式(某些实现具有不同的环视语法):

rx = /^(?!apple$|orange$|juice$)/

【讨论】:

    【解决方案2】:

    我注意到apple-juice 应该根据你的参数匹配,但是apple juice 呢?我假设如果您正在验证 apple juice,您仍然希望它失败。

    所以 - 让我们构建一组算作“边界”的字符:

    /[^-a-z0-9A-Z_]/        // Will match any character that is <NOT> - _ or 
                            // between a-z 0-9 A-Z 
    
    /(?:^|[^-a-z0-9A-Z_])/  // Matches the beginning of the string, or one of those 
                            // non-word characters.
    
    /(?:[^-a-z0-9A-Z_]|$)/  // Matches a non-word or the end of string
    
    /(?:^|[^-a-z0-9A-Z_])(apple|orange|juice)(?:[^-a-z0-9A-Z_]|$)/ 
       // This should >match< apple/orange/juice ONLY when not preceded/followed by another
       // 'non-word' character just negate the result of the test to obtain your desired
       // result.
    

    在大多数正则表达式风格中,\b 算作“单词边界”,但“单词字符”的标准列表不包括 -,因此您需要创建一个自定义列表。如果您不尝试捕获 -,它可以与 /\b(apple|orange|juice)\b/ 匹配...

    如果您只测试“单字”测试,您可以使用更简单的方法:

    /^(apple|orange|juice)$/ // and take the negation of this...
    

    【讨论】:

      【解决方案3】:

      这得到了一些方式:

      ((?:apple|orange|juice)\S)|(\S(?:apple|orange|juice))|(\S(?:apple|orange|juice)\S)
      

      【讨论】:

        【解决方案4】:
        \A(?!apple\Z|juice\Z|orange\Z).*\Z
        

        将匹配整个字符串,除非它只包含一个禁用词。

        或者,如果您没有使用 Ruby,或者您确定您的字符串不包含换行符,或者您设置了 ^ 和 $ 在行首/行尾不匹配的选项

        ^(?!apple$|juice$|orange$).*$
        

        也可以。

        【讨论】:

          【解决方案5】:

          这里有一些简单的复制粘贴代码,不仅适用于精确字词异常。


          复制/粘贴代码:

          在以下正则表达式中,仅用您的正则表达式替换全大写部分。

          Python 正则表达式
          pattern = r"REGEX_BEFORE(?>(?P<exceptions_group_1>EXCEPTION_PATTERN)|YOUR_NORMAL_PATTERN)(?(exceptions_group_1)always(?<=fail)|)REGEX_AFTER"
          
          红宝石正则表达式
          pattern = /REGEX_BEFORE(?>(?<exceptions_group_1>EXCEPTION_PATTERN)|YOUR_NORMAL_PATTERN)(?(<exceptions_group_1>)always(?<=fail)|)REGEX_AFTER/
          
          PCRE正则表达式
          REGEX_BEFORE(?>(?<exceptions_group_1>EXCEPTION_PATTERN)|YOUR_NORMAL_PATTERN)(?(exceptions_group_1)always(?<=fail)|)REGEX_AFTER
          
          JavaScript

          在 2020 年 6 月 17 日之前不可能,并且在不久的将来可能不会。



          完整示例

          REGEX_BEFORE = \b
          YOUR_NORMAL_PATTERN = \w+
          REGEX_AFTER =
          EXCEPTION_PATTERN = (苹果|橙子|果汁)

          Python 正则表达式
          pattern = r"\b(?>(?P<exceptions_group_1>(apple|orange|juice))|\w+)(?(exceptions_group_1)always(?<=fail)|)"
          
          红宝石正则表达式
          pattern = /\b(?>(?<exceptions_group_1>(apple|orange|juice))|\w+)(?(<exceptions_group_1>)always(?<=fail)|)/
          
          PCRE正则表达式
          \b(?>(?<exceptions_group_1>(apple|orange|juice))|\w+)(?(exceptions_group_1)always(?<=fail)|)
          



          它是如何工作的?

          这使用了相当复杂的正则表达式,即原子组、条件、Lookbehinds 和命名组。

          1. (?&gt; 是原子组的开始,这意味着它不允许回溯:这意味着,如果该组匹配一次,但后来由于后向失败而失效,那么整个组将不匹配。 (在这种情况下,我们想要这种行为)。

          2. (?&lt;exceptions_group_1&gt; 创建一个命名的捕获组。它比使用数字更容易。请注意,该模式首先尝试查找异常,如果找不到异常,则返回到正常模式。

          3. 请注意,原子模式首先尝试查找异常,如果找不到异常,则返回到正常模式。

          4. 真正的魔力在于(?(exceptions_group_1)。这是一个询问 exceptions_group_1 是否成功匹配的条件。如果是,那么它会尝试查找always(?&lt;=fail)。这种模式(正如它所说的那样)总是会失败,因为它会寻找“always”这个词,然后它会检查“does "ways"=="fail"',但它永远不会。

          5. 因为条件失败,这意味着原子组失败,并且因为它是原子的,这意味着它不允许回溯(试图寻找正常模式),因为它已经匹配了异常。

          这绝对不是这些工具的预期用途,但它应该可靠且高效地工作。



          Ruby 中原始问题的准确答案

          /\b(?>(?<exceptions_group_1>(apple|orange|juice))|\w+)(?(<exceptions_group_1>)always(?<=fail)|)/
          

          与其他方法不同,此方法可以修改为拒绝任何模式,例如任何不包含子字符串“apple”、“orange”或“juice”的单词。

          /\b(?>(?<exceptions_group_1>\w*(apple|orange|juice))|\w+)(?(<exceptions_group_1>)always(?<=fail)|)/
          

          【讨论】:

            【解决方案6】:

            类似(PHP)的东西

            $input = "The orange apple gave juice";
            if(preg_match("your regex for validating") && !preg_match("/apple|orange|juice/", $input))
            {
              // it's ok;
            }
            else
            {
              //throw validation error
            }
            

            【讨论】:

            • 除非匹配 applejuice 并因此引发验证错误。
            猜你喜欢
            • 1970-01-01
            • 2023-01-16
            • 2021-04-20
            • 1970-01-01
            • 2021-04-20
            • 2022-08-18
            • 1970-01-01
            • 2021-09-27
            • 1970-01-01
            相关资源
            最近更新 更多