我从数据库中拉出汽车子模型,我正在动态构建我的正则表达式。
以下是搜索字符串的示例: EX-L轿车4门
这是我的正则表达式: preg_match(" / LX | EX | EX-L | LX-P | LX-S / Ui",$ input_line,$ output_array);
由于某种原因,输出是EX而不是EX-L,因为它应该是。有人可以解释原因吗?
答案 0 :(得分:2)
您的模式是非锚定的,因此匹配子字符串的第一个替代方法使正则表达式引擎停止处理整个组。这是NFA正则表达式的常见行为。
此外,您的模式中没有量词,因此/U
修饰符是多余的。
所以,你可以使用
/EX-L|LX-P|LX-S|LX|EX/i
这是一种可读的形式。但是,使用正则表达式的最佳做法是确保没有替代分支可以在与另一个分支相同的位置匹配。这意味着你可以使用
/EX(-L)?|LX(-[PS])?/i
答案 1 :(得分:0)
正如其他人所指出的那样,这种不良结果的原因是因为你的模式没有锚点(例如:^
,{{1},因此正则表达式引擎很乐意拥有第一个替代方案并为门运行。和其他一些鲜为人知的人)。这与您在php $
条件下看到的相同的短路行为相同;如果if($x || $y)
为真,则无需进一步评估。但足够......
我想提供一些我认为与您的案例/问题相关的其他逻辑。
你说你的正则表达式是动态构建的,所以我假设你的方法是这样的:
用户可以识别要搜索的子字符串/关键字。
$x
如前所述,您需要更长的字符串才能在具有相同起始字符的较短字符串之前。
$strings=array('LX','EX','EX-L','LX-P','LX-S');
// array of substrings in any order
使用implode()将所有字符串传递到单个正则表达式模式。
rsort($strings);
// sort DESC, longer strings precede shorter strings when leading characters match
虽然可以通过编程方式将类似的字符串缩小为Wiktor推荐的简洁模式,但使用即时模式可能不值得。
最后正常运行preg_match()。
$piped_regex='/\b(?:'.implode('|',$array).')\b/i';
// word boundaries ensure the string is not part of a larger word; remove if not desired
// pattern: /\b(?:LX-S|LX-P|LX|EX-L|EX)\b/i
我希望走出这种方法对你和未来的SO读者有所帮助。