PHP - Preg_match shortest matches - php

I'm trying to get "content" from this string:
$string = "start start content end";
with preg_match like this:
preg_match('/start(.*?)end/', $string, $matches);
echo $match[1];
but, problem is $matches[1] returns start content not only content because there are two start in $string (and maybe more)
How to get only content part with preg_match?

Using a negative lookahead:
$string = "start start content end";
preg_match('/start\h*((?:(?!start).)*)end/', $string, $matches);
echo $matches[1];
// content
(?:(?!start).) will match any character if that is not followed by start.

You can add + to eat all start and then capture your required string.
(?:start\s)+(.+?)end

Related

regex for specific url id

I want to change the id partner=852501 to partner=985412 in my code, but stuck in this step. Example:
http://a-ads.com/?partner=852501
My attempt:
([1-z0-9\/]+)\/\/(a-ads\.com\/?)
How to do the right thing?
Regex: partner=\K[^&]+
Details:
\K resets the starting point of the reported match
[^&]+ Match a single character not present in the list & one and unlimited times
PHP code:
preg_replace('/partner=\K[^&]+/', '985412', $url);
preg_replace you can replace the value
$string = 'http://a-ads.com/?partner=852501';
$your = 985412;
echo preg_replace('/(\d+)/', $your, $string);
UPD: The value can be obtained with the help of preg_match
preg_match('/partner=(\d+)/', $string, $match);
echo $match[1];

Find next word after colon in regex

I am getting a result as a return of a laravel console command like
Some text as: 'Nerad'
Now i tried
$regex = '/(?<=\bSome text as:\s)(?:[\w-]+)/is';
preg_match_all( $regex, $d, $matches );
but its returning empty.
my guess is something is wrong with single quotes, for this i need to change the regex..
Any guess?
Note that you get no match because the ' before Nerad is not matched, nor checked with the lookbehind.
If you need to check the context, but avoid including it into the match, in PHP regex, it can be done with a \K match reset operator:
$regex = '/\bSome text as:\s*'\K[\w-]+/i';
See the regex demo
The output array structure will be cleaner than when using a capturing group and you may check for unknown width context (lookbehind patterns are fixed width in PHP PCRE regex):
$re = '/\bSome text as:\s*\'\K[\w-]+/i';
$str = "Some text as: 'Nerad'";
if (preg_match($re, $str, $match)) {
echo $match[0];
} // => Nerad
See the PHP demo
Just come from the back and capture the word in a group. The Group 1, will have the required string.
/:\s*'(\w+)'$/

Regex with PHP preg_replace() need to find the nearest name in string

I need to find the nearest name in string how would I do this ?
The closest I got was the apposite and it finds the furthest away from string is:
$string = "joe,bob,luis,sancho,bob,marco,lura,hannah,bob,marco,luis";
$new_string = preg_replace('/(bob(?!.*bob))/', 'found it!', $string);
echo $new_string;
<!-- outputs: joe,bob,luis,sancho,bob,marco,lura,hannah,found it!,marco,luis -->
How would I do the apposite ? and have an output like this:
<!-- outputs: joe,found it!,luis,sancho,bob,marco,lura,hannah,bob,marco,luis -->
The regex you are using (bob(?!.*bob)) matches the last occurrence of bob (not as a whole word) on a line, because the . matches any character but a newline, and the negative lookahead makes sure there is no bob after bob. See what your regex matches (if we use preg_replace with default options).
You may use
$re = '/\bbob\b/';
$str = "joe,bob,luis,sancho,bob,marco,lura,hannah,bob,marco,luis";
$result = preg_replace($re, 'found it!', $str, 1);
See IDEONE demo
The regex \bbob\b will match a whole word, and using the limit argument will only match the first occurrence of the word 'bob'.
See preg_replace help:
limit
The maximum possible replacements for each pattern in each subject string. Defaults to -1 (no limit).
You can try a negative lookbehind instead, like this
$string = "joe,bob,luis,sancho,bob,marco,lura,hannah,bob,marco,luis";
$new_string = preg_replace('/((?<!bob)bob)/', 'found it!', $string, 1);
echo $new_string;
<!-- outputs: joe,found it!,luis,sancho,bob,marco,lura,hannah,bob,marco,luisoff -->
As Wiktor said, use the limit option to match only the first occurrence of the name.

php get grouped values in Regex

i am using php Regular expressions but i can't retrieve values that i group using ()
this is my input
<img src="http://www.example.com/image.jpg" title="title" />
i need only src value , this is my regex '"<img src=\"(.*?)\".*?\/>"'
if i can retrieve First group just like java patterns my problem is sloved
preg_match_all('"<img src=\"(.*?)\".*?\/>"', $source, $re);
print_r($re);
and it return full image tag like this <img src="http://www.example.com/image.jpg" title="title" />
To match a single string, preg_match function is enough. You don't need to go for preg_matchall function. If you want to match more number of strings then you could use preg_matchall function. And also first try to match the exact string through the pattern rather than to go for grouping. If it's impossible to match a particular string then go for grouping.
In the below, matching the exact value of src attribute is done.
You could get the value of src in two ways,
1. positive lookbehind
Regex:
(?<=src=\")[^\"]*
PHP code:(Through match_all)
<?php
$string = "<img src=\"http://www.example.com/image.jpg\" title=\"title\" />";
$regex = '~(?<=src=\")[^\"]*~';
preg_match_all($regex, $string, $matches);
print_r($matches);
?>
PHP code:(Through match)
<?php
$string = "<img src=\"http://www.example.com/image.jpg\" title=\"title\" />";
$regex = '~(?<=src=\")[^\"]*~';
if (preg_match($regex, $string, $m)) {
$yourmatch = $m[0];
echo $yourmatch;
}
?> //=> http://www.example.com/image.jpg
Explanation:
(?<=src=\") Positive look-behind is used here. So the regex engine puts the match marker just after to the src=".
[^\"]* Now it starts matching any character zero or more times but not of ". When it finds a ", it stops matching characters.
2. Using \K
Regex:
src=\"\K[^\"]*
PHP code (through match)
<?php
$string = "<img src=\"http://www.example.com/image.jpg\" title=\"title\" />";
$regex = '~src=\"\K[^\"]*~';
if (preg_match($regex, $string, $m)) {
$yourmatch = $m[0];
echo $yourmatch;
}
?> //=> http://www.example.com/image.jpg
Explanation:
\K resets the starting point of the reported match. Any previously consumed characters are no longer included in the final match.
src=\"\K So it discards the previously matched src=".
[^\"]* Matches any character zero or more times but not of "
You're using preg_match_all so that you need to pass index as well, use print_r($re[1]); to get results.
I Got It Accidently !
we can Code Like this for first Grouped
print_r($re[1]);

preg matching and replacing elements

Hi how do I do a preg match on
$string1 = "[%refund%]processed_by"
$string2 = "[%refund%]date_sent"
I want to grab the bits inside %% and then remove the [%item%] altogether. leaving just the "proccessed_by" or "date_sent" I have had a go below but come a bit stuck.
$unprocessedString = "[%refund%]date_sent"
$match = preg_match('/^\[.+\]/', $unprocessedString);
$string = preg_replace('/^\[.+\]/', $unprocessedString);
echo $match; // this should output refund
echo $string; // this should output date_sent
Your problem is with your use of the preg_match function. It returns the number of matches found. But if you pass it a variable as a third parameter, it stores the matches for the entire pattern and its subpatterns in an array.
So you can capture both of the parts you want in subpatterns with preg_match, which means you don't need preg_replace:
$unprocessedString = "[%refund%]date_sent"
preg_match('/^\[%(.+)%\](.+)/', $unprocessedString, $matches);
echo $matches[1]; // outputs 'refund'
echo $matches[2]; // outputs 'date_sent'

Categories