Reputation: 13
i have for example the following string
@kirbypanganja[Kirby Panganja] elow @kyraminerva[Kyra] test @watever[watever ever evergreen]
I want to get the substring that match with @username[Full Name], Im really new on regex thing. Im using the ff code:
$mention_regex = '/@([A-Za-z0-9_]+)/i';
preg_match_all($mention_regex, $content, $matches);
var_dump($matches);
where the $content is the string above. what should be the correct regex so that i can have the array @username[Full Name] format?
Upvotes: 1
Views: 83
Reputation: 47874
I'll start with a very direct, one-liner method that I believe is best and then discuss the other options...
Code (Demo):
$string = "@kirbypanganja[Kirby Panganja] elow @kyraminerva[Kyra] test @watever[watever ever evergreen]";
$result = preg_split('/]\K[^@]+/', $string, 0, PREG_SPLIT_NO_EMPTY);
var_export($result);
Output:
array (
0 => '@kirbypanganja[Kirby Panganja]',
1 => '@kyraminerva[Kyra]',
2 => '@watever[watever ever evergreen]',
)
Pattern (Demo):
] #match a literal closing square bracket
\K #forget the matched closing square bracket
[^@]+ #match 1 or more non-at-signs
My pattern takes 12 steps, which is the same step efficiency as Pedro's pattern.
There are two benefits to the coder by using preg_split()
:
preg_match_all()
which means it can be used as a one-liner without a condition statement.preg_match_all()
. This means the the entire returned array is instantly ready to unpack without any subarray accessing.In case you are wondering what the 3rd and 4th parameters are in preg_split()
, the 0
value means return an unlimited amount of substrings. This is the default behavior, but it is used as a placeholder for parameter 4. PREG_SPLIT_NO_EMPTY
effectively removes any empty substrings that would have been generated by trying to split at the start or end of the input string.
That concludes my recommended method, now I'll take a moment to compare the other answers currently posted on this page, and then present some non-regex methods which I do not recommended.
The most popular and intuitive method is to use a regex pattern with preg_match_all()
. Both Sahil and Pedro have opted for this course of action. Let's compare the patterns that they've chosen...
Sahil's pattern /@[A-Za-z0-9_]+\[[a-zA-Z\s]+\]/i
correctly matches the desired substrings in 18 steps, but uses unnecessary redundancies like using the i
modifier/flag despite using A-Za-z
in the character class. Here is a demo. Also, [A-Za-z0-9_]
is more simply expressed as \w
.
Pedro's pattern /@[^]]+]/
correctly matches the desired string in 12 steps. Here is a demo.
By all comparisons, Pedro's method is superior to Sahil's because it has equal accuracy, higher efficiency, and increased pattern brevity. If you want to use
preg_match_all()
, you will not find a more refined regex pattern than Pedro's.
That said, there are other ways to extract the desired substrings. First, the more tedious way that doesn't involve regex that I would never recommend...
Regex-free method: strpos()
& substr()
$result = [];
while (($start = strpos($string, '@')) !== false) {
$result[] = substr($string, $start, ($stop = strpos($string, ']') + 1) - $start);
$string = substr($string, $stop);
}
var_export($result);
Coders should always entertain the idea of a non-regex method when dissecting strings, but as you can see from this code above, it just isn't sensible for this case. It requires four function calls on each iteration and it isn't the easiest thing to read. So let's dismiss this method.
Here is another way that provides the correct result...
$result = [];
foreach (explode('@', $string) as $v) {
if ($v) {
$result[] = '@' . substr($v, 0, strrpos($v, ']') + 1);
}
}
It makes fewer function calls compared to the previous regex-free method, but it still too much handling for such a simple task.
At this point, it is the clear that the most sensible methods should be using regex. And there is nothing wrong with choosing preg_match_all()
-- if this were my project, I might elect to use it. However, it is important to consider the direct-ness of preg_split()
. This function is just like explode()
but with the ability to use a regex pattern. This question is a perfect stage for preg_split()
because the substrings that should be omitted can also be used as the delimiter between the desired substrings.
Upvotes: 0
Reputation: 98881
You can use:
@[^]]+]
i.e.:
$string = "@kirbypanganja[Kirby Panganja] elow @kyraminerva[Kyra] test @watever[watever ever evergreen]";
preg_match_all('/@[^]]+]/', $string, $result);
print_r($result[0]);
Output:
Array
(
[0] => @kirbypanganja[Kirby Panganja]
[1] => @kyraminerva[Kyra]
[2] => @watever[watever ever evergreen]
)
Upvotes: 1
Reputation: 15141
Regex: /@[A-Za-z0-9_]+\[[a-zA-Z\s]+\]/
/@[A-Za-z0-9_]+\[[a-zA-Z\s]+\]/
this will matchExample:
@thanSomeCharacters[Some Name Can contain space]
<?php
$content='@kirbypanganja[Kirby Panganja] elow @kyraminerva[Kyra] test @watever[watever ever evergreen]';
$mention_regex = '/@[A-Za-z0-9_]+\[[a-zA-Z\s]+\]/i';
preg_match_all($mention_regex, $content, $matches);
print_r($matches);
Upvotes: 0