The problem with your regular expression is that it matches @
even when it is preceded by whitespace. Because \s
will match the whitespace, it will be captured into $matches
array. You can solve this problem by using lookarounds. In this case, it can be solved with a positive lookbehind:
preg_match_all('/(?<=^|\s)@([^@ ]+)/', $test, $matches);
This will match the part after @
only if it is preceded by a space or beginning-of-the line anchor. It's important to note that lookarounds do not actually consume characters. They just assert that the given regular expression is either followed or preceded by something.