PHP regex for #[mention] - php

Can someone help me:
$pattern = "/^(?:[a-zA-Z0-9?. ]?)+#([a-zA-Z0-9]+)(.+)?$/";
$str = "Hey #[14256] hey how are you?";
preg_match($pattern, $title, $matches);
print_r($matches);
The print result works fine if I remove the brackets (#[14256]) of the # mention, however I can't figure out how to do the regex to work with the brackets. So I will get the result 14256 in my array.

You need to include the brackets in your regex:
"/^(?:[a-zA-Z0-9?. ]?)+#(\\[?[a-zA-Z0-9]+\\]?)(.+)?$/"
Notice the \\[? and \\]? I've added; those will match the [] characters, and will also match if there is no [].
Keep in mind, the above will match #[14256 and #14256]. If you want to only match one or the other, you need to do it a little differently.
"/^(?:[a-zA-Z0-9?. ]?)+#([a-zA-Z0-9]+|\\[[a-zA-Z0-9]+\\])(.+)?$/"
This will match EITHER #aA1 or #[aA1], but not the bad examples as I showed above.
One last thing to include: This regex will only match one instance of the #[mention]. If you want to match ALL instances of it (such as in "hey #123, how is #456 these days?"), use the following with preg_match_all():
"/#([a-zA-Z0-9]+|\\[[a-zA-Z0-9]+\\])/"
Then $matches[1] will contain both 123 and 456.

You need to escape the brackets in your regex so they don't get interpreted as a new character class. Try this instead (it will only capture the number, not the brackets. Place the escaped brackets in the parentheses to capture them as part of a backreference):
$pattern = "/^(?:[a-zA-Z0-9?. ]?)+#\[([a-zA-Z0-9]+)\](.+)?$/";

Related

How to preg_match '{95}1340{113}1488{116}1545{99}1364'

i want to preg_match following as it is
$this_string = '{95}1340{113}1488{116}1545{99}1364';
My best try was
preg_match('/^[\{\d+\}\d+]+$/', $this_string);
That matches
{95}1340{113}1488
but also
{95}1340{113}
which is wrong.
I know why it is matching last example. One match {95}1340 was true, so '+' 'll be always true. But i don't know how to tell, if it match, so it has always be a complete match in '[…]'
i do expect only matches likes these
{…}…
{…}…{…}…
{…}…{…}…{…}…
one of the tries:
^(\{\d+\}\d+)+$
does also match
{99}1364
at the very last end of this string as a second match, so i get back an Array with two Elements:
Array[0] = {95}1340{113}1488{116}1545{99}1364 and
Array[1] = {99}1364
Problem is unnecessary use of character class in your regex i.e. [ and ].
You can use:
'/^(\{\d+\}\d+)+$/'
The translation of your regex to a clearer thing would be: /^[\{\}0-9+]+$/, this would be explained as everything that is inside this chracters {}0123456789+, exactly those ones.
What you want is grouping, for grouping, parentheses are needed and not character classes () instead [], so what you want to do is replace [] for ().
Short answer: '/^(\{\d+\}\d+)+$/'
What you are trying to do is a little unclear. Since your last edit, I assume that you want to check the global format of the string and to extract all items (i.e. {121}1231) one by one. To do that you can use this code:
$str = '{95}1340{113}1488{116}1545{99}1364';
$pattern = '~\G(?:{\d+}\d+|\z)~';
if (preg_match_all($pattern, $str, $matches) && empty(array_pop($matches[0])))
print_r($matches[0]);
\G is an anchor for the start of the string or the end of the previous match
\z is an anchor for the end of the string
The alternation with \z is only needed to check that the last match is at the end of the string. If the last match is empty, you are sure that the format is correct until the end.

issues with preg_match PHP

I have a string:
$str="(94896)content is here(/94896)(94897)content is here(/94897)(94898)content is here(/94898)(94899)content is here(/94899)";
the (number) and (/number) act as tags to take certain content out of the string.
and I have a preg_match to take the content out:
if(preg_match('/(94896)\"(.*)\"(\/94896)/',$str,$c)) {echo "I found the content, its:".$co[1];}
Now for some reason, it doesn't find a match in the string ($str), though its clearly there....
Any ideas on what im doing wrong here?
You need to take the double-quotes out of your regex string, since they don't appear in $str, but are expected by the regex.
'/(94896)\"(.*)\"(\/94896)/'
// ^^ ^^
// These aren't in the string.
EDIT: I think you'll also need to escape your brackets, since they will be getting read as grouping operators, not actual brackets.
Your expression should be:
'/\(94896\)(.*)\(\/94896\)/'
Parentheses are used in a regex to denote subpatterns. If you want to search these characters in a string, you must escape them:
preg_match('/\(94896\)(.*)\(\/94896\)/',$str,$c)
If the pattern is found:
echo "I found the content, its:".$c[0];
Oh, and as Karl Nicoll says, why are the quotations in your pattern?
To match all content:
$str="(94896)content is here(/94896)(94897)content is here(/94897)(94898)content is here(/94898)(94899)content is here(/94899)";
$re = '/\((\d+)\)(.*)\(\/\1\)/';
preg_match_all($re, $str, $matches,PREG_SET_ORDER);
var_dump($matches);
Number will be in $matches[*][1], content in $matches[*][2].

How can use a match in the same regex in php?

I have this string (that is a serialized variable in php):
s:12:"hello "world";
and I wanna to find "hello "world" only with regex, I try this, but seems it is stupid :P
(s:(?P<num>[0-9]+):".{\k{num}}";)
I only want to know how I can use "num" result in the its regex?
this regex is used in a big regex so I can't check for end of string.
thanks advance!
You can use your named capturing groups as backreference like this
Back references to the named subpatterns can be achieved by (?P=name)
or, since PHP 5.2.2, also by \k or \k'name'. Additionally PHP
5.2.4 added support for \k{name} and \g{name}.
According to php.net
But I think this can be used only to match the found pattern again, but not as a number in a quantifier. (At least I didn't got it to work.)
You can use preg_match function, which will populate an array of matches:
If matches is provided, then it is filled with the results of search. $matches[0] will contain the text that matched the full pattern, $matches1 will have the text that matched the first captured parenthesized subpattern, and so on.
More information about preg_match: PHP: preg_match
$text = 's:12:"hello "world";s:12:"good bue world";';
$pattern = "(.*:[0-9]+:\"(.*)\";.*)U";
preg_match_all($pattern,$text,$r);

Matches text inside brackets with Regex in PHP

I have some text like:
name: [my_name]
email: [my_email]
I'd like to grab the fields in square brackets with regex—how would I do that?
I've tried using this pattern: [*.?]
Unfortunately it doesn't work. PHP gives this error:
compilation failed: nothing to repeat at offset 0
What's wrong? Is the pattern correct?
The brackets are special characters in regex. To match them you'll have to escape them with a back-slash. Something like \[(.*?)\]. Adding the parens () captures whatever is matched inside it so you you can use it later. Otherwise you're just matching on the whole pattern and you'd have to manually strip the brackets.
You should move the * and escape the [ and ]. So make it \[.*\] Since . matches any character already and * says: 0 or more of that char. So .* is 0 or more of any char
No, you got the order wrong. It should be something like
\[(.*)\]
.* = Something repeated as many times as possible.
The compilation error you get is because the compiler does not now what to repeat, as [ is a special character in regular expressions. The ? you added would also allow nothing within the brackets, which I figured you don't want, so I removed it. The question mark makes the foregoing statement optional. The parentheses aroudn the .* are used to capture the result. If you don't add those, the regex will match, but you won't get whats inside the brackets as result.
<?php
$text =
"name: [my_name]
email: [my_email]";
$pattern = '/\[(.*)\]/';
$matches = array();
preg_match_all($pattern, $text, $matches);
$name = $matches[1][0];
$email = $matches[1][1];
print "$name<br />";
print "$email";
?>
will output
my_name
my_email
/ is the delimiter (not part of the actual pattern per se). The \ is for escaping the [ and ] brackets, as they define character class definitions in patterns when not escaped. ( and ) define subpatterns, which means that text captured by a subpattern will be put into the array referenced by the third parameter of preg_match_all (in this case $matches).
Escape it!
[ and ] special characters, so you need to escape them:
\[*.?\]

PHP Regex question

I'm trying to parse some text for example:
$text = "Blah blah [a]findme[/a] and [b]findmetoo[b], maybe also [z]me[/z].";
What I have now is:
preg_match_all("/[*?](.*?)[\/*?]/", $text, $matches);
Which doesn't work unfortunately.
Any ideas how to parse, return the node key and the corresponding node value?
Well firstly by you not putting () around your *? your not matching the tag name, and secondly, using [*?] will match multiple [ until the ] where you want to match inside, so you should be doing [(.*?)] and [\/(.*?)]
You would have to try something along the lines of:
/\[(.*?)\](.*?)\[\/(.*?)\]/is
this is not guaranteed to work but will get you closer.
you could also do:
/\[(.*?)\](.*?)\[\/\1\]/is
and then foreach result loop recursively until preg_match_all returns false, that's a possible way how to do nesting.
In order to match the same tags, you need a backreference:
This assumes no nesting, if you need nesting then let me know.
$matches = array();
if (preg_match_all('#\[([^\]]+)\](.+?)\[/\1\]#', $text, $matches)) {
// $matches[0] - entire matched section
// $matches[1] - keys
// $matches[2] - values
}
Incidentally, I do not know what you are going to do with this bbcode style work, but usually you would want to use preg_replace_callback() to deal with inline modification of this sort of text, with a regexp similar to the above.
Try:
$pattern = "/\[a\](.*?)\[\/a\]/";
$text = "Blah blah [a]findme[/a] and [b]findmetoo[b], maybe also [z]me[/z].";
preg_match_all($pattern, $text, $matches);
That should point you in the right direction.
I came up with this regex ((\[[^\/]\]).+?(\[\/[^\/]\])). Hope will work for you
I'm no regex monkey, but I think you need to escape those brackets and create groups to search for, as brackets don't return results (parentheses do):
preg_match_all("/\\[(*?)\\](.*?)\\[\(\/*?)\\]/", $text, $matches);
Hope this works!
Should your second example also be captured even though the [b] "tag" is not closed with the [\b] backslash 'b'. If tags should be properly closed then use
/\[(.*?)\](.*?)\[\/\1\]/
This will ensure that opening and closing tags match.
You can try this:
preg_match_all("/\[(.*?)\](.*?)\[\/?.*?\]/", $text, $matches);
See it
Changes made:
[ and ] are regex meta-characters
used to define character class. To
match literal [ and ] you need to
escape them.
To match any arbitrary text(without
newline) in non-greedy way you use
.*?.
To match the node key you need to
enclose the pattern matching it in
(..) so that they get captured.

Categories