如何使用PHP正则表达式从逻辑表达式字符串中提取独立逻辑子句?
解决逻辑表达式子句提取问题
我来帮你搞定这个问题!你当前的正则表达式没能正确拆分出独立逻辑子句,主要是因为贪婪匹配和断言位置不对,而且没考虑引号内的内容。下面一步步给你说明解决方案:
问题根源分析
你写的正则/(.+)(?!AND|OR)(.+)/s存在两个关键问题:
- 贪婪匹配:
.+会尽可能多地吞掉整个字符串,直接匹配到输入的末尾; - 断言无效:负向预查
(?!AND|OR)的位置放在了第一个.+之后,而字符串末尾本来就没有AND/OR,所以正则直接把整个输入当成了一个匹配项。
另外,这个正则也没考虑子句中包含引号的情况(比如你示例里的"static"),如果引号内出现AND/OR(虽然示例没有),也会被误分割。
正确解决方案
我们可以用preg_split来拆分字符串,以**不在引号内的AND/OR**作为分隔符,这样既能准确拆分出子句,又不会破坏引号内的内容。代码如下:
$input = 'pageType == "static" OR pageType == "item" AND pageRef == "index"'; // 以不在引号内的AND/OR作为分隔符拆分字符串 $clauses = preg_split('/(?<!\")\b(AND|OR)\b(?!\")/', $input, -1, PREG_SPLIT_NO_EMPTY); // 清理每个子句前后的空格 $clauses = array_map('trim', $clauses); // 输出结果 foreach ($clauses as $index => $clause) { echo "$index => $clause\n"; }
正则解释
/(?<!\")\b(AND|OR)\b(?!\")/的各个部分作用:
(?<!\"):负向回顾后发断言,确保分隔符前面没有双引号,避免把引号内的AND/OR当成分隔符;\b:单词边界,确保匹配的是完整的AND/OR单词,不会误匹配比如ANDROID里的AND;(AND|OR):匹配作为分隔符的逻辑运算符;(?!\"):负向先行断言,确保分隔符后面没有双引号,同样避免干扰引号内的内容。
执行结果
运行上面的代码后,你会得到期望的输出:
0 => pageType == "static" 1 => pageType == "item" 2 => pageRef == "index"
如果你坚持要用preg_match_all,也可以用这个正则来直接匹配子句:
preg_match_all('/(?:^|(?<=\b(AND|OR)\b))\s*([^"](?:[^"]|\"[^"]*\")*?)\s*(?=\b(AND|OR)\b|$)/', $input, $matches); $clauses = array_map('trim', $matches[2]);
不过preg_split的写法更简洁直观,推荐使用。
内容的提问来源于stack exchange,提问作者FSodic
相关产品推荐
相关产品推荐

