Why preg_match(“/[^(22|75)]/”, “25”) returns false?

前端 未结 5 1668
误落风尘
误落风尘 2021-01-29 08:31

I want to test that a given string does not belong to the following group of strings: 22 75.

Could anyone please tell why PHP\'s preg_match(\"/[^(22|75)]/\

5条回答
  •  既然无缘
    2021-01-29 09:03

    What are character classes

    A character class is a collection of characters (not strings). With a character class, you're telling the regex engine to match only one out of several characters.

    For example, if you wanted to match an a or e, you'd write [ae]. If you wanted to match grey or gray, you'd write gr[ae]y.

    Explanation for first regex

    [^(22|75)]
    

    As said above, character classes match a single character from the list. Here, you're using ^ to get a negated character class, so this will match a single character that's not in the supplied list. In this case, our list contains the following characters:

    ( 2 2 | 7 5 )
    

    Multiple characters are only counted once. So this effectively becomes:

    ( 2 | 7 5 )
    

    25 is the string you're matching against. The regular expression asks: Does the supplied string contains a single character that's not in the above list? 2 and 5 are in the list, so the answer is No. That explains why preg_match() returns false (not false, 0 to be precise).

    Explanation for second regex

    /[^(22|76)]/
    

    It is same as above. The only difference here is that 5 changed to 6. It now checks for the absense of any of the following characters:

    ( 2 | 7 6 )
    

    The supplied string is still the same as before - 25. Does the string contain any character that's not in the list above? Yes! It does contain 5 (which is not in the list anymore). That explains why preg_match() returns 1.

    Difference between character classes and alternation

    They look similar but they do different things. Alternation can be used when you want to match a single regular expression out of several possible regular expressions. Unlike character classes, alternation works with a regex. A simple string, say foo is also a valid regular expression. It matches f followed by o, followed by o.

    Use character class when you want to match one of the included characters. Use alternation when you want to match between n number of strings.

    How should you modify the regex to obtain correct results

    Negate your preg_match() call and use the regex (22|75):

    if (!preg_match('/(22|75)/', '25')) {
        # code...
    }
    

    This is the easiest approach. If you want to achieve this directly using a regex, then you may want to use look-arounds.

    Alternative solution

    If this is exactly what you're trying to do, then you don't need a regular expression at all. Leverage PHP's built-in functions for string manipulation! Not only it will be faster, it will be more readable too.

    In this case, a simple in_array() should suffice:

    if(!in_array('25', array(25,75))) {
        # code ...
    }
    

提交回复
热议问题