【问题标题】:preg_match: and-not expressionpreg_match: and-not 表达式
【发布时间】:2015-04-15 22:18:16
【问题描述】:

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

例如:

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

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

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

【问题讨论】:

  • 试过类似if(!preg_match("/(lorem.*?ipsum|ipsum.*?lorem)/is", $str)) { /* code */ }?
  • 单词边界,区分大小写如何?如果您对ipsum 存在而lorem 不存在时的字符串匹配感到满意,我会选择^(?si)(?!.*\blorem\b.*\bipsum\b|\bipsum\b.*\blorem\b.*$).*$。见regex101.com/r/lB5qX5/1
  • @WarGasm 您似乎在评论几乎所有不起作用的东西,而不是唯一真正按照您的要求做的事情。总帐。
  • 那么您是说lorem 是必需的吗?因为当我阅读您的问题时,我看到的是if it contains lorem, it can't contain ipsum,而不是it must contain lorem, but not ipsum。对我说“如果文本有……”意味着它是可选的,不是必需的。如果需要,则可以使用像这样的简单模式:/(?=.*lorem)(?!.*ipsum).*/is,这意味着must have lorem, can't have ipsum。也添加所有边界的东西。它已经是多行的。 Demo
  • 您接受了一个与您的问题要求的没有 lorem 的句子匹配的答案,实际上,接受的答案匹配:“无”和“绝对没有”,这真的很难过(对你来说)。跨度>

标签: php regex preg-match


【解决方案1】:

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

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 在他的评论中指出的那样:

另外,如果您想在不需要否定 preg_match 的情况下完成这项工作,您可以将其包装在一个零宽度的负组中,例如:^(?!lorem[\s\S]*ipsum|ipsum[\s\S]lorem).*$。这将匹配两个单词都不存在的整个字符串。 Demo(在您删除其中一个字词之前显示为不匹配)。

【讨论】:

  • 另外,如果你想在不需要否定 preg_match 的情况下完成这项工作,你可以将它包装在一个零宽度的负组中,例如:^(?!lorem[\s\S]*ipsum|ipsum[\s\S]lorem).*$。这将匹配两个单词都不存在的整个字符串。 Demo(在您删除其中一个词之前显示为不匹配)。
  • 差不多合适,谢谢回复。但它需要 preg_match 的“not”运算符。我怎么能离开它?问题出在另一个测试中。我有一系列规则,并希望将此测试包含在 preg_match 的一个周期中。
  • @JonathanKuhn 非常有用,谢谢。刚刚添加到答案中
  • @WarGasm 用 Jonathan cmets 更新了答案
  • @WarGasm 这不是你想要的吗?因为你在要求中没有说什么。
【解决方案2】:

使用这个:

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

制作两种不同的正则表达式模式比制作一个长正则表达式更容易

【讨论】:

  • 缺少分隔符。此外,如果您只搜索一个词,stripos 会更好。这也不考虑 ipsum 而没有 lorem
  • @JonathanKuhn 哎呀,对不起。我不熟悉PHP,只知道正则表达式。感谢您的关注
  • 关键是通常更容易将您的任务拆分为不同正则表达式的两次调用,而不是将所有工作都塞进一个正则表达式中。
【解决方案3】:

我建议的正则表达式不需要!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)) {
  ...
}

【讨论】:

  • SO 要求“如果文本包含“lorem”但任何行都没有“ipsum”,那么它应该成功”。在没有 lorem 和 ipsum 的情况下尝试它,它也匹配。这将返回 true dolor sit amet, consectetur adipisicing elit
  • 根据您的要求,应该。如果您不想要它,请使用^(?si)(?!.*?\bipsum\b.*$)(?!.*\blorem\b.*\bipsum\b|\bipsum\b.*\blorem\b.*$).*$ - regex101.com/r/lB5qX5/4。编辑 2.
  • @PedroLobito 对,但尝试在您的演示中留下“lorem”,您将获得匹配。这不是“AND-NOT”逻辑。
  • 这正是SO想要匹配lorem但不存在ipsum的匹配项
  • @stribizhev 太完美了!谢谢!
【解决方案4】:

其实如果正则表达式有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";
}

【讨论】:

    【解决方案5】:
    $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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-05
      • 1970-01-01
      • 2021-10-01
      相关资源
      最近更新 更多