Using delimiters with preg_match - php

I am having difficulties to understand preg_match function.An e.g is way better
$subject="XY=abC%3Fedr%3Damp;35"
I am trying to extract
bC%3Fed
using preg_match and store it in variable
if(preg_match($pattern, $subject, $matches))
{
$string = $matches[1];
}
echo $string;
Here are the different variation that i use for $pattern
I want to use # as a delimeter
#bC(.*?)#
#bC.*?#
I just don't understand why its not working , i guess something is wrong in the $pattern.
Please don't use complicated regex and try to fix my attempt as the aim here is to understand how preg_match works and what is wrong here.
Regards

Using # as the delimiter is OK, but the regex is wrong. I guess you want:
#(bC.*?)r# // matches #bC and the following characters unless and 'r' (see comments)
A good starting point to learn the regex syntax is the PCRE manual
Example:
$subject="XY=abC%3Fedr%3Damp;35";
$pattern="#(bC.*?)r#";
preg_match($pattern, $subject, $matches);
$string = $matches[1];
echo $string; // bC%3Fed

The ? after .* switches the greediness of the pattern. By default patterns are greedy, they try to find the longest match. So you .*? means any char, any count, smallest match. Because here is nothing after that will anchor it, the smallest possible match is an empty string.

Related

Regular expression return only certain values PHP

I cant remember what to use to return only a specific part of a string.
I have a string like this:-
$str = "return(me or not?)";
I want to get the word which is after (. In this example me will be my result. How can I do this?
I dont think substr is what I am looking for. as substr returns value based on the index you provided. which in this case i dont know the index, it can vary. All I know is that I want to return whatever is after "(" and before the space " ". The index positions will always be different there for i cant use substr(..).
This regular expression should do the trick. Since you didn't provide general rules but only an example it might need further changes though.
preg_match('/\((\S+)/', $input, $matches);
$matches[1] contains "me" then.
<?php
// Your input string
$string = "return(me or not?)";
// Pattern explanation:
// \( -- Match opening parentheses
// ([^\s]+) -- Capture at least one character that is not whitespace.
if (preg_match('/\(([^\s]+)/', $string, $matches) === 1)
// preg_match() returns 1 on success.
echo "Substring: {$matches[1]}";
else
// No match found, or bad regular expression.
echo 'No match found';
Result of capture group will be your result using this regex and preg_match().
$regex = '/\((\w+)/';
Check preg_match() for the working reference.

Cannot understand preg_match pattern

Please explain to me when $string will be true. I cannot find all information by Google.
preg_match('#^[0-9a-f]{32}$#', $string)
{32} means $string must contain 32 chars? [0-9a-f] is mean that only numeric and lower case must be in $string?
I have validation where I check if preg_match is true. But I cannot understand $string template.
$string is the subject you are searching on.
$pattern = '/0x[\da-f]/i';
preg_match($pattern, $subject, $matches);
print_r($matches);
Read the docs. As for return values of this function, if you just care for existence of a match...
preg_match() returns 1 if the pattern matches given subject, 0 if it does not, or FALSE if an error occurred.
I'm pretty sure you can't use the # symbol for regex, you need a forward slash. I have:
if(preg_match("/[^0-9]/", $data)){$data=null}
This will evaluate if the input data is a number. There is A LOT you can do with regex ... what is it you need to do? Perhaps a more specific question about what you need it to do and what you have tried?

preg_replace with Regex - find number-sequence in URL

I'm a regex-noobie, so sorry for this "simple" question:
I've got an URL like following:
http://stellenanzeige.monster.de/COST-ENGINEER-AUTOMOTIVE-m-w-Job-Mainz-Rheinland-Pfalz-Deutschland-146370543.aspx
what I'm going to archieve is getting the number-sequence (aka Job-ID) right before the ".aspx" with preg_replace.
I've already figured out that the regex for finding it could be
(?!.*-).*(?=\.)
Now preg_replace needs the opposite of that regular expression. How can I archieve that? Also worth mentioning:
The URL can have multiple numbers in it. I only need the sequence right before ".aspx". Also, there could be some php attributes behind the ".aspx" like "&mobile=true"
Thank you for your answers!
You can use:
$re = '/[^-.]+(?=\.aspx)/i';
preg_match($re, $input, $matches);
//=> 146370543
This will match text not a hyphen and not a dot and that is followed by .aspx using a lookahead (?=\.aspx).
RegEx Demo
You can just use preg_match (you don't need preg_replace, as you don't want to change the original string) and capture the number before the .aspx, which is always at the end, so the simplest way, I could think of is:
<?php
$string = "http://stellenanzeige.monster.de/COST-ENGINEER-AUTOMOTIVE-m-w-Job-Mainz-Rheinland-Pfalz-Deutschland-146370543.aspx";
$regex = '/([0-9]+)\.aspx$/';
preg_match($regex, $string, $results);
print $results[1];
?>
A short explanation:
$result contains an array of results; as the whole string, that is searched for is the complete regex, the first element contains this match, so it would be 146370543.aspx in this example. The second element contains the group captured by using the parentheeses around [0-9]+.
You can get the opposite by using this regex:
(\D*)\d+(.*)
Working demo
MATCH 1
1. [0-100] `http://stellenanzeige.monster.de/COST-ENGINEER-AUTOMOTIVE-m-w-Job-Mainz-Rheinland-Pfalz-Deutschland-`
2. [109-114] `.aspx`
Even if you just want the number for that url you can use this regex:
(\d+)

preg_match_all issue

I'am trying to get all {{product.smth}} with preg_match_all, but if i have few of this in one line i get wrong result.
Example:
$smth = '<name>{{product.name}}</name><getname>{{product.getName()}}</getname>';
$pattern = '/\{\{product\.(.*)\}\}/';
preg_match_all($pattern, $smth, $matches);
//returns '{{product.name}}</name><getname>{{product.getName()}}'
//instad of '{{product.name}}' and '{{product.getName()}}'
What iam doing wrong? Please help.
The problem is that repetition is greedy. Either make it ungreedy by using .*? or better yet: disallow the } character for the repetition:
$pattern = '/\{\{product\.([^}]*)\}\}/';
If you do want to allow single } in that value (like {{product.some{thing}here}}), the equivalent solution uses a negative lookahead:
$pattern = '/\{\{product\.((?:(?!\}\}).)*)\}\}/';
For every single character included in .* it checks that that character doesn't mark the start of a }}.
I think it'll work if you change .* to .*? this will make it lazy instead of greedy and it will try to match as little as possible - so, till the first occurance of }} rather than the last.

Need help with a PHP preg_match

I'm not very good with preg_match so please forgive me if this is easy. So far I have...
preg_match("/".$clear_user."\/[0-9]{10}/", $old_data, $matches)
The thing I'm trying to match looks like..
:userid/time()
Right now, the preg_match would have a problem with 22/1266978013 and 2/1266978013. I need to figure out how to match the colon.
Also, is there a way to match all the numbers until the next colon instead of just the next 10 numbers, because time() could be more or less than 10.
try this as your pattern:
#:$userId/[0-9]+#
preg_match("#:$userId/[0-9]+#", $old_data, $matches);
preg_match("/:*".$clear_user."\/[0-9]{10}/", $old_data, $matches);
You need to extend your match and include in your pattern the : delimiter.
Failing in doing so lead to the erratic behaviour you already experienced.
By the way, it is not so erratic: take in account the two cases you filed:
22/1266978013 and 2/1266978013.
The regex engine matches :2(2/1266978013):(2/1266978013) your pattern two times. If you comprehend the field delimitator (:) you can be shure that only the intended target will be affected.
I would use preg_replace to directly substitute the pattern you found,
once you fire the expensive regular expression engine, you should, to me, let it to perform as much work it can.
$pattern='#:'.$clear_user.'/[0-9]{10}#';
$replacement = ":$clear_user/$new_time"
$last_message=preg_replace($pattern, $replacement, $old_data ,-1,$matches);
if (!$matches) {
$last_message .= $replacement;
}

Categories