PHP Reverse Preg_match

时间:2011-04-18 14:06:01

标签: php regex if-statement preg-match reverse

if(preg_match("/" . $filter . "/i", $node)) {
    echo $node;
}

此代码过滤变量以决定是否显示变量。 $ filter的示例条目是“office”或“164(。*)976”。

我想知道是否有一种简单的说法:如果$ filter与$ node不匹配。以正则表达式的形式?

所以......不是“if(!preg_match”,而是更多的$ filter =“!office”或“!164(。*)976”但是有效吗?

3 个答案:

答案 0 :(得分:10)

如果您肯定想使用“负正则表达式”而不是简单地反转正面正则表达式的结果,则可以这样做:

if(preg_match("/^(?:(?!" . $filter . ").)*$/i", $node)) {
    echo $node;
}
如果字符串不包含$filter中的正则表达式/子字符串,

将匹配该字符串。

说明:(以office作为示例字符串)

^          # Anchor the match at the start of the string
(?:        # Try to match the following:
 (?!       # (unless it's possible to match
  office   # the text "office" at this point)
 )         # (end of negative lookahead),
 .         # Any character
)*         # zero or more times
$          # until the end of the string

答案 1 :(得分:6)

您正在寻找(?!...) negative assertion

要排除某个字符串出现在主题中的任何位置,您可以使用此双断言方法:

preg_match('/(?=^((?!not_this).)+$)  (......)/xs', $string);

它允许指定任意(......)主正则表达式。但是如果你只想禁止一个字符串,你可以把它留下来。

答案 2 :(得分:0)

马里奥的答案2是正确的答案,原因如下:

首先回答Justin Morgan的评论,

  

我很好奇,你知道这会有什么表现吗?   与!preg_match()方法相反?我不在某个地方   我可以测试它们。 - Justin Morgan 2011年4月19日21:53

暂时考虑门逻辑。

何时取消preg_match():当找到一个匹配并且你希望条件为1)对于缺少所需的正则表达式为真,或者2)为正则表达式存在时为假。

何时在正则表达式上使用否定断言:在查找匹配项时,如果字符串仅与正则表达式匹配,则您希望条件为真,如果找到其他任何内容则失败。如果您确实需要测试不需要的字符,同时允许省略允许的字符,则必须这样做。

否定(preg_match()=== 1)的结果只测试正则表达式是否存在。如果需要“bar”且不允许使用数字,则以下操作无效:

if (preg_match('bar', 'foo2bar') === 1) {
  echo "found 'bar'"; // but a number is here, so fail.
}

if (!pregmatch('[0-9]', 'foobar') === 1) {
  echo "no numbers found"; // but didn't test for 'bar', so fail.
}

因此,为了真正测试多个正则表达式,初学者将使用多个preg_match()调用进行测试......我们知道这是一种非常业余的方法。

因此,Op想要测试字符串是否存在可能的正则表达式,但是如果字符串至少包含其中一个,则条件只能传递为true。对于大多数简单的情况,简单地否定preg_match()就足够了,但对于更复杂或更广泛的正则表达式模式,它不会。我将使用我的情况来实现更真实的场景:

假设您想拥有一个人姓名的用户表单,尤其是姓氏。您希望系统接受所有字母,无论大小写和位置如何,接受连字符,接受撇号和排除所有其他字符。我们知道,匹配所有不需要的字符的正则表达式是我们首先想到的,但想象一下你支持UTF-8 ...那是很多字符!您的程序将几乎与UTF-8表一样大,只需一行!我不关心你有什么硬件,你的服务器应用程序对命令的长度有限制,更不用说200个带括号的子模式的限制,所以整个UTF-8字符表(减[AZ],[az] ], - 和')太长了,不要介意程序本身会很大!

因为我们不会使用if(!preg_match('。#\\ $ \%...这可能很长而且无法评估...在字符串上查看字符串是否错误,我们应该测试更简单的方法,在正则表达式上使用断言负面外观,然后使用以下方法否定整体结果:

<?php
  $string = "O'Reilly-Finlay";
  if (preg_match('/?![a-z\'-]/i', $string) === 0) {
    echo "the given string matched exclusively for regex pattern";
    // should not work on error, since preg_match returns false, which is not an int (we tested for identity, not equality)
  } else {
    echo "the given string did not match exclusively to the regex pattern";
  }
?>

如果我们只查找正则表达式[a-z \' - ] / i,我们所说的只是“匹配字符串,如果它包含任何这些东西”,那么不会测试坏字符。如果我们否定了该函数,我们会说“如果找到包含任何这些东西的匹配则返回false”。这也不对,所以我们需要说“如果我们匹配任何不在正则表达式中的任何东西,则返回false”,这是通过前瞻完成的。我知道铃声正在某个人的头脑中消失,而且他们正在考虑通配符扩展风格......不,前瞻不会这样做,它只会对每场比赛做出否定,并继续。因此,它检查正则表达式的第一个字符,如果它匹配,它继续前进,直到找到不匹配或结束。完成后,发现与正则表达式不匹配的所有内容都返回到匹配数组,或者只返回1.简而言之,在正则表达式'a'上断言否定与匹配正则表达式'b'相反,其中'b'包含一切都不能与'a'匹配。非常适用于“b”不合适的时候。

注意:如果我的正则表达式中有错误,我道歉...我过去几个月一直在使用Lua,所以我可能会混合我的正则表达式规则。否则,'?!'是PHP的正确预测语法。