preg_match: and-not 表达式

preg_match: and-not expression

我有一个带换行符的文本,我需要检查它是否有某个词,但没有另一个词。

例如:

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

如果文本有单词 "lorem" AND "ipsum",无论在哪一行,测试都应该失败。如果文本包含 "lorem" 但任何一行都没有 "ipsum",那么它应该会成功。

我可能会做一些解决方法,并使用条件、explodestrpos 函数进行测试。但是我想使用正则表达式规则作为预定义的预设,这样我就可以轻松地扩展功能。

您可以像这样使用正则表达式:

lorem[\s\S]*ipsum|ipsum[\s\S]lorem

working demo

$re = "/lorem[\s\S]*ipsum|ipsum[\s\S]lorem/i"; 
$str = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."; 

if (!preg_match($re, $str, $matches)) {
     // your code here
}

更新: 你可以在不否定 preg_match 的情况下实现相同的效果,因为 Jonathan Kuhn 在他的评论中指出:

Also, if you wanted to make this work without needing to negate the preg_match you could wrap it in a zero-width negative group like: ^(?!lorem[\s\S]*ipsum|ipsum[\s\S]lorem).*$. This will match the entire string where both words don't exist. Demo (shows as not matching until you remove one of the words).

使用这个:

$str = "Lorem my string ipsum";
if (preg_match("/lorem/", $str) && !preg_match("/ipsum/", $str)) {
    //code here
}

制作 2 个不同的正则表达式模式比使用一个长正则表达式更容易

$string ="Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore ipsum et dolore magna aliqua.";

$string2 ="Lorem dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.";

loremIpsum  ($string );
//string contrains lorem and ipsum
loremIpsum  ($string2 );
//string only contrain lorem

function loremIpsum  ($string){
    if (!preg_match('/(lorem.*?ipsum|ipsum.*?lorem)/sim', $string)) {

        if (preg_match('/lorem/sim', $string )) {
            # Successful match
            echo "string only contain lorem"; // TRUE
        }else{
            echo "string doesn't contain lorem"; //FALSE
        }

    }else{
        echo "string contrains lorem and ipsum"; //FALSE
    }
}

DEMO

实际上,如果正则表达式有一个 and 运算符会很好,但至少我不知道这样的事情,所以你可以在正则表达式中将它们与 or 运算符匹配,然后使用 array_intersect 来检查。

$checkArray = array ('lorem', 'ipsum');
$haystack = "lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.";

$matched = preg_match_all("/lorem|ipsum/i", $haystack, $result, PREG_PATTERN_ORDER);

if ($matched && count($checkArray) == count(array_intersect($checkArray,$result[0]))) {
    echo "Gotcha";
}

我建议的正则表达式不需要 !preg_match,并且只匹配一个多行字符串,没有任何大写或小写的 "lorem" 和 "ipsum",并且作为整个单词:

^(?si)(?!.*?\bipsum\b.*$)(?!.*\blorem\b.*\bipsum\b|\bipsum\b.*\blorem\b.*$).*$

(?si) 设置不区分大小写和单行模式,以便 . 可以匹配换行符并匹配 "Lorem" 和 "lorem"。 \bs 仅用于匹配整个单词。它还将使具有 ipsum 的字符串失败(第二个条件 (?!.*?\bipsum\b.*$) 设置为处理该字符串)。

demo here

$re = "/^(?si)(?!.*?\bipsum\b.*$)(?!.*\blorem\b.*\bipsum\b|\bipsum\b.*\blorem\b.*$).*$/"; 
$str = "dolor lorem sit amet, consectetur adipisicing elit, \nsed do eiusmod tempor incididunt ut labore et dolore magna aliqua."; 
if (preg_match($re, $str, $matches)) {
  ...
}