Problem (un-)greedy RegExp - php

Consider the following Strings:
1: cccbbb
2: cccaaabbb
I would like to end up with are matches like this:
1: Array
(
[1] =>
[2] => bbb
)
2: Array
(
[1] => aaa
[2] => bbb
)
How can I match both in one RegExp?
Here's my try:
#(aaa)?(.*)$#
I have tried many variants of greedy and ungreedy modifications but it doesn't work out. As soon as I add the '?' everything is matched in [2]. Making [2] ungreedy doesn't help.
My RegExp works as expected if I omit the 'ccc', but I have to allow other characters at the beginning...

/(aaa)?((.)\3*)$/
There will be an extra [3] though. I don't think that's a problem.

Thanks for the brainstorming here guys! I have finally been able to figure something out that's working:
^(?:([^a]*)(aaa))?(.*)$

here's a non-regex way. search and split on "aaa" if found, then store the rest of the right side of "aaa" into array.
$str="cccaaabbb";
if (strpos($str,"aaa")!==FALSE){
$array[]="aaa";
$s = explode("aaa",$str);
$array[]=end($s);
}
print_r($array);
output
$ php test.php
Array
(
[0] => aaa
[1] => bbb
)
As for [1], depending on what's your criteria when "aaa" is not found, it can be as simple as getting the substring from character 4 onwards using strpos().

this will match the groups but its not very flexible can you put a little more detail of what you need to do. It may be much easier to grab three characters a time and evaluate them.
Also I tested this in poweshell which has a slightly different flavor of regex.
(a{3,3})*(b{3,3})

do like this:
$sPattern = "/(aaa?|)(bbb)/";
this works well.

Related

PHP : Matching strings between two strings

i have a problem with preg_match , i cant figure it out.
let the code say it :
function::wp_statistics_useronline::end
function::wp_statistics_visitor|today::end
function::wp_statistics_visitor|yesterday::end
function::wp_statistics_visitor|week::end
function::wp_statistics_visitor|month::end
function::wp_statistics_visitor|total::end
these are some string that run functions inside php;
when i use just one function::*::end it works just fine.
but when it contain more than one function , not working the way i want
it parse the match like :
function::wp_statistics_useronline::end function::wp_statistics_visitor|today::end AND ....::end
so basically i need Regex code that separate them and give me an array for each function::*::end
I assume you were actually using function::(.*)::end since function::*::end is never going to work (it can only match strings like "function::::::end").
The reason your regex failed with multiple matches on the same line is that the quantifier * is greedy by default, matching as many characters as possible. You need to make it lazy: function::(.*?)::end
It's pretty straight forward:
$result = preg_match_all('~function::(\S*)::end~m', $subject, $matches)
? $matches[1] : [];
Which gives:
Array
(
[0] => wp_statistics_useronline
[1] => wp_statistics_visitor|today
[2] => wp_statistics_visitor|yesterday
[3] => wp_statistics_visitor|week
[4] => wp_statistics_visitor|month
[5] => wp_statistics_visitor|total
)
And (for the second example):
Array
(
[0] => wp_statistics_useronline
[1] => wp_statistics_visitor|today
)
The regex in the example is a matching group around the part in the middle which does not contain whitespace. So \S* is a good fit.
As the matching group is the first one, you can retrieve it with $matches[1] as it's done after running the regular expression.
This is what you're looking for:
function\:\:(.*?)\:
Make sure you have the dot matches all identifier set.
After you get the matches, run it through a forloop and run an explode on "|", push it to an array and boom goes the dynamite, you've got what you're looking for.

regular expression that matches the below pattern

I'm not good in regular expression, but today I faced an unavoidable situation, So I need a regular expression that matches the case below:
|hhas.jpg||sd22-9393das.png||8jjas.png||IMG00338-20110109.jpg|
I tried this regex : /(?<=\|)(\w|\d+\.\w+)(?=\|)/i but not getting the desired results...
I want to match all the strings by using preg_match function of PHP between two | signs ie hhas.jpg, sd22-9393das.png etc...
You can use the following regex:
/\|([^|]*)\|/gi
Demo
Matched strings:
1. hhas.jpg
2. sd22-9393das.png
3. 8jjas.png
4. IMG00338-20110109.jpg
Use this..
preg_match_all('/\|(.*?)\||/', $str, $matches);
print_r(array_filter($matches[1]));
OUTPUT :
Array
(
[0] => hhas.jpg
[1] => sd22-9393das.png
[2] => 8jjas.png
[3] => IMG00338-20110109.jpg
)
Demonstration
your expression :
/(?<=\|)(\w|\d+\.\w+)(?=\|)/i
pretty well written , but just has a few minor flaws
when you say \w that is only one character.
the OR condition
\d+\.\w+ will match only when it meets the same order. i.e. list of digits first followed by a . and then followed by letters or digits or underscore.
better change your regex to :
/(?<=\|)(.*?)(?=\|)/ig
this will give you anything which is between |s
also IMHO , using lookarounds for such a problem is an overkill. Better use :
/\|(.*?)\|/ig
Try without using regular expression.
explode('||', rtrim(ltrim ('|hhas.jpg||sd22-9393das.png||8jjas.png||IMG00338-20110109.jpg|','|'),'|'));
Output:
Array ( [0] => hhas.jpg [1] => sd22-9393das.png [2] => 8jjas.png [3] => IMG00338-20110109.jpg )

PHP preg_match: comma separated decimals

This regex finds the right string, but only returns the first result. How do I make it search the rest of the text?
$text =",415.2109,520.33970,495.274100,482.3238,741.5634
655.3444,488.29980,741.5634";
preg_match("/[^,]+[\d+][.?][\d+]*/",$text,$data);
echo $data;
Follow up:
I'm pushing the initial expectations of this script, and I'm at the point where I'm pulling out more verbose data. Wasted many hours with this...can anyone shed some light?
heres my string:
155.101.153.123:simple:mass_mid:[479.0807,99.011, 100.876],mass_tol:[30],mass_mode: [1],adducts:[M+CH3OH+H],
130.216.138.250:simple:mass_mid:[290.13465,222.34566],mass_tol:[30],mass_mode:[1],adducts:[M+Na],
and heres my regex:
"/mass_mid:[((?:\d+)(?:.)(?:\d+)(?:,)*)/"
I'm really banging my head on this one! Can someone tell me how to exclude the line mass_mid:[ from the results, and keep the comma seperated values?
Use preg_match_all rather than preg_match
From the PHP Manual:
(`preg_match_all`) searches subject for all matches to the regular expression given in pattern and puts them in matches in the order specified by flags.
After the first match is found, the subsequent searches are continued on from end of the last match.
http://php.net/manual/en/function.preg-match-all.php
Don't use a regex. Use split to split apart your inputs on the commas.
Regexes are not a magic wand you wave at every problem that happens to involve strings.
Description
To extract a list of numeric values which may include a single decimal point, then you could use this regex
\d*\.?\d+
PHP Code Example:
<?php
$sourcestring=",415.2109,520.33970,495.274100,482.3238,741.5634
655.3444,488.29980,741.5634";
preg_match_all('/\d*\.?\d+/im',$sourcestring,$matches);
echo "<pre>".print_r($matches,true);
?>
yields matches
$matches Array:
(
[0] => Array
(
[0] => 415.2109
[1] => 520.33970
[2] => 495.274100
[3] => 482.3238
[4] => 741.5634
[5] => 655.3444
[6] => 488.29980
[7] => 741.5634
)
)

Why does this regex capture produce 2 matches?

I do not know why there are 2 matches found aside from the input using this regex, when I expected only 1 match.
preg_match(/_(\d(-\d){0,3})\./,$str,$matches);
on this file string format name_A-B-C-D.ext.
I would expect to get a single match like this:
Example A
[0] => name_A-B-C-D.ext
[1] => A-B-C-D
Example B
[0] => name_A-B-C.ext
[1] => A-B-C
But this is the result I get:
Example A
[0] => name_A-B-C-D.ext
[1] => A-B-C-D
[2] => -D
Example B
[0] => name_A-B-C.ext
[1] => A-B-C
[2] => -C
I only wish to capture A up to D if its preceded with a hyphen.
This code is usable and I can simply ignore the 2nd match, but I would like to know why its there. I can only assume it has something to do with my two capture groups. Where is my error ?
Yes, you get two captures because you have two capturing groups in your regular expression.
To avoid the unwanted capture you could use a non-capturing group (?:...):
/_(\d(?:-\d){0,3})\./
I can only assume it has something to do with my two capture groups.
Your assumption is correct
Where is my error ?
There is no error, everything is behaving as expected.
You have to groups in your RE, so you get 2 matches. What is surprising?
Each pair of parenthesis is a group.

Split in series PHP

i have this string ++++++1DESIGNRESULTSM25Fe415(Main)
and i have similar string about 2000 lines from which i want to split these..
[++++++] [1] [DESIGNRESULTS] [M25] [Fe415] [(Main)]
from the pattern only the 2nd 4h and 5th value changes
eg.. ++++++2DESIGNRESULTSM30Fe418(Main) etc..
what i actually want is:
Split the first value [++++++]
Split the value after 4 Character of [DESIGNRESULTS] so ill get this [M25]
Split the value before 4 Character of [(Main)] so ill get this [Fe415]
After all this done store the final chunk of piece in an array.
the similar output what i want is
Array ( [0] => 1 [1] => M25 [2] => Fe415 )
Please help me with this...
Thanks in advance :)
Your data split needs are a bit unclear. A regular expression that will get separate matches on each of the chunks you first specify:
(\++)(\d)(DESIGNRESULTS)(M\d\d)(Fe\d\d\d)(\(Main\))
If you only need the two you are asking for at the end, you can use
(\d)DESIGNRESULTS(M\d\d)(Fe\d\d\d)
You could also replace \d\d with \d+ if the number of digits is unknown.
However, based on your examples it looks like each string chunk is a consistent length. It would be even faster to use
array(
substr($string, 6, 1)
//...
)
How about this
$str = "++++++1DESIGNRESULTSM25Fe415(Main)";
$match = array();
preg_match("/^\+{0,}(\d)DESIGNRESULTS(\w{3})(\w{5})/",$str,$match);
array_shift($match);
print_r($match);

Categories