php - 稍微复杂的正则表达式,用于匹配后面的否定外观,后跟一个精确的短语

标签 php regex pcre

所以我有以下正则表达式:

(?<!\.)\b([\w\@\-]+) *\b(IN|NOT IN|LIKE|NOT LIKE|BETWEEN|REGEXP|NOT|IS|XOR)+\b *

我希望它能帮助我匹配一些 SQL 代码。

但是,看起来我对第二个括号中的短语有问题,例如“不在”和“不喜欢”

我需要一个匹配或不匹配的正则表达式(没有像我当前正则表达式的工作方式那样的部分匹配)。

  1. customers.id NOT IN (SELECT MAX(customers_service.customer_id))根本不应该匹配
  2. customers.id NOT LIKE (SELECT MAX(customers_service.customer_id))根本不应该匹配
  3. id NOT IN (SELECT MAX(customers_service.customer_id))应该匹配
  4. id IN (SELECT MAX(customers_service.customer_id))应该匹配

我使用 RegexBuddy 进行检查,并使用我的正则表达式获得了 1 号和 2 号的匹配项。

另外,

  1. id NOT IN (SELECT MAX(customers_service.customer_id))仅匹配id NOT ,而不是 id NOT IN
  2. id NOT LIKE (SELECT MAX(customers_service.customer_id))仅匹配id NOT ,而不是 id NOT LIKE

我想修改这个正则表达式来捕获否定查找的条件,以及第二个括号中的确切短语,或者根本不匹配(无部分)。

我怎样才能完成这个工作?

最佳答案

首先,\b与单词的开头或结尾不匹配。人们总是这么描述它,但这是一个谎言。什么\b匹配是一个后跟单词字符但前面没有一个的位置-- (?=\w)(?<!\w) -- 或者前面有一个单词字符,后面没有一个-- (?<=\w)(?!\w) 。如果这些条件不完全是您想要匹配的,那么您最好不要使用 \b根本不。

您尝试匹配的名称显然可以包含 @-以及标准的“单词”字符(字母、数字和下划线),因此单词边界毫无用处。一般来说,为了确保匹配完整的单词,您可以使用否定后向查找和否定先行查找:

(?<![\w@-])[\w@-]+(?![\w@-])

就您而言,您还需要确保前面的字符不是 . ,并且您知道以下字符必须是空格,因此正则表达式的该部分将是:

(?<![.\w@-])[\w@-]+\s+

更大的问题是,这也可能匹配您不想要的内容,即像 NOT 这样的关键字。和IN 。我建议两种补救措施。首先,收紧关键字的正则表达式,以便复合关键字,如 NOT INNOT LIKE被视为原子单位:

(?:NOT(?:\s+(?:IN|LIKE))?|IN|LIKE|BETWEEN|REGEXP|IS(?:\s+NOT)?|XOR)\b

其次,在前瞻中使用它来确保您匹配的第一个单词不是关键字(的一部分)。这是完整的正则表达式,为了可读性分为两行:

(?<![.\w@-])(?!(?:NOT(?:\s+(?:IN|LIKE))?|IN|LIKE|BETWEEN|REGEXP|IS|XOR)\b)[\w@-]+\s+
(?:NOT(?:\s+(?:IN|LIKE))?|IN|LIKE|BETWEEN|REGEXP|IS|XOR)\b\s*

您可以通过为关键字定义子例程组来使其更易于维护。这是 PHP 字符串文字的样子:

'~
(?(DEFINE)(?<KEYWORD>
  (?:NOT(?:\s+(?:IN|LIKE))?|IN|LIKE|BETWEEN|REGEXP|IS(?:\s+NOT)?|XOR)\b
))
(?<![.\w@-])(?!(?&KEYWORD))[\w@-]+\s+(?&KEYWORD)\s*
~ix'

...这是一个 demo

关于php - 稍微复杂的正则表达式,用于匹配后面的否定外观,后跟一个精确的短语,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14072396/

相关文章:

java - 字符串正则表达式之间的字符串

Python:在字符串中搜索变量重复字符

regex - 在 Tcl 中实现 "quotemeta"\Q ...\E ?

regex - 匹配小数

php - 我如何在magento中找到dispatchEvent方法?

python - 在Python中获取括号内的字符串

php - jQuery 自动完成结果应显示为组合框

PHP 正确的正则表达式在带有 unicode 的 PHP 5.3.3-7 中不起作用

php - 从 2 个数据库表中选择进行显示

php - 使用 AWS SDK for PHP 获取 SQS 队列中的所有消息