I need get all matches in string, when word begins with @
and then contains only alnym 0-9a-z
characters. for example from this string @ww@ee x@@vx @ss @aa assadd @sfsd
I need get these pieces:
@ss
@aa
@sfsd
I am trying:
$str = "@ww@ee x@@vx @ss @aa assadd @sfsd";
preg_match_all("#(^|\s)\@([0-9a-z]+)(\s+|$)#ui", $str, $matches);
var_dump( $matches );
But this gives only @ss
@sfsd
and skips @aa
.
What would be right pattern for this?
You can use the following regex
'~\B(?<!@)@([0-9a-z]+)(?:\s|$)~iu'
See the regex demo and here is an IDEONE demo:
$re = '~\B(?<!@)@([0-9a-z]+)(?:\s|$)~ui';
$str = "@ww@ee x@@vx @ss @aa assadd @sfsd";
preg_match_all($re, $str, $matches);
print_r($matches);
The regex explanation:
\B
- match the non-word boundary location (that is, everywhere but between ^
and \w
, \w
and $
, \W
and \w
, \w
and \W)
)(?<!@)
- fail the match if there is a @
before the current location@
- a @
symbol (does not have to be escaped)([0-9a-z]+)
- Group 1 (since the (...)
are not escaped, they capture a subpattern and store it in a special memory slot)(?:\s|$)
- a non-capturing group (only meant to group alternatives) matching a whitespace (\s
) or $
.The ~ui
modifiers allow proper handling of Unicode strings (u
) and make the pattern case insensitive (i
).
Note that \B
is forcing a non-word character to appear before @
. But you do not want to match if another @
precedes the @wwww
-like string. Thus, we have to use the negative lookbehind (?<!@)
that restricts the matches even further.