PHP - Preg_match_all optional match - php

I'm having problems matching the[*] which is sometimes there and sometimes not. Anyone have suggestions?
$name = 'hello $this->row[today1][] dfh fgh df $this->row[test1] ,how good $this->row[test2][] is $this->row[today2][*] is monday';
echo $name."\n";
preg_match_all( '/\$this->row[.*?][*]/', $name, $match );
var_dump( $match );
output:
hello $this->row[test] ,how good $this->row[test2] is $this->row[today][*] is monday
array (
0 =>
array (
0 => '$this->row[today1][*]',
1 => '$this->row[test1] ,how good $this->row[test2][*]',
2 => '$this->row[today2][*]',
),
)
Now the [0][1] match takes on too much because it is matching until the next '[]' instead of ending at '$this->row[test]' . I'm guessing the [*]/ adds a wildcard. Somehow need to check if the next character is [ before matching to []. Anyone?
Thanks

[, ] and * are special meta characters in regex and you need to escape them. Also you need to make last [] optional as per your question.
Following these suggestions following should work:
$name = 'hello $this->row[today1][] dfh fgh df $this->row[test1] ,how good $this->row[test2][] is $this->row[today2][*] is monday';
echo $name."\n";
preg_match_all( '/\$this->row\[.*?\](?:\[.*?\])?/', $name, $match );
var_dump( $match );
OUTPUT:
array(1) {
[0]=>
array(4) {
[0]=>
string(20) "$this->row[today1][]"
[1]=>
string(17) "$this->row[test1]"
[2]=>
string(19) "$this->row[test2][]"
[3]=>
string(21) "$this->row[today2][*]"
}
}

Related

Regular expression - repeat groups

I have text:
<b>Title1:</b><br/><b>Title2:</b> Value1<br/><b>Title3:</b> Value2<br/><b>Title4:</b> Value3<br/>Value4<b>Title5:</b> Value5<br/>
What regex to get:
[0] => <b>Title1:</b><br/>
[1] => <b>Title2:</b> Value1<br/>
[2] => <b>Title3:</b> Value2<br/>
[3] => <b>Title4:</b> Value3<br/>Value4
[4] => <b>Title5:</b> Value5<br/>
My variant not working:
<b>(.*?)</b>(.*?)
You can use preg_split() with a lookahead:
<?php
$split = preg_split( '/(?=<b>Title\d+:)/', '<b>Title1:</b><br/><b>Title2:</b> Value1<br/><b>Title3:</b> Value2<br/><b>Title4:</b> Value3<br/>Value4<b>Title5:</b> Value5<br/>' );
array_shift( $split );
var_dump( $split );
Output:
array(5) {
[0]=>
string(19) "<b>Title1:</b><br/>"
[1]=>
string(26) "<b>Title2:</b> Value1<br/>"
[2]=>
string(26) "<b>Title3:</b> Value2<br/>"
[3]=>
string(32) "<b>Title4:</b> Value3<br/>Value4"
[4]=>
string(26) "<b>Title5:</b> Value5<br/>"
}
Your regex was close, you need:
<b>(.*?)<\/b>(.*?)(?=<b>|$)
https://regex101.com/r/dk67IK/1
A resource like this can be very useful in troubleshooting regex: https://regex101.com/
Looks like you are missing an escape character in <b>(.*?)</b>(.*?)
<b>(.*?)<\/b>(.*?) should stop an error from being thrown for that current regex and get you close to the result, you'll need to work with it a bit more to get the exact results you want though.
<b>(.*?)<\/b>(.*?)<br\/> should be a bit closer I think as it looks like you want to include the break tags.

Get a strings between brackets with regular expressions and php preg_match_all

I have several texts with custom macro tags in it. I want to parse the content of these tags but I'd like to treat the ones with parameters in it differently.
I need to construct valid URLs out of these bracket contents.
Example:
This is my text:
{gallery}events/2016-02-18-Sunny-Sport-Day,single=IMG_0336.jpg,salign=left{/gallery}
Hey there! We had a great day with a tough but funny competition. Our
team had a great race and was able to finish in second place.
{gallery}events/2016-02-18-Sunny-Sport-Day{/gallery}
{gallery}team/members{/gallery}
So I need to extract the path parts of the string between the {gallery} tags but I don't want to match those with parameters such as "single=IMG_0336.jpg,salign=left" because these are treated separately.
I need something which does the following:
{gallery}events/2016-02-18-Sunny-Sport-Day,single=IMG_0336.jpg,salign=left{/gallery}
becomes
first output: events/2016-02-18-Sunny-Sport-Day
second output: IMG_0336.jpg
and
{gallery}events/2016-02-18-Sunny-Sport-Day{/gallery}
becomes
events/2016-02-18-Sunny-Sport-Day
Tried the following regex:
/\{gallery\}(.*?)(?!single=)\{\/gallery\}/
But it allways matches the whole string including the single parameter.
To get the content of the single parameter I tried the following:
/,single=(.*?),/
This works fine for the single paramter only but I don't know how to get everything together.
Conclusion:
In a PHP environment I would like to have as output two arrays. The first consists only of the folders:
events/2016-02-18-Sunny-Sport-Day
team/members
and a second array which consists of the single file paths:
events/2016-02-18-Sunny-Sport-Dayist/IMG_0336.jpg
This method will extract your desired substrings and prepare the output data as you have requested: Pattern Demo
PHP Code: (Demo)
$str="{gallery}events/2016-02-18-Sunny-Sport-Day,single=IMG_0336.jpg,salign=left{/gallery}
Hey there! We had a great day with a tough but funny competition. Our team had a great race and was able to finish in second place.
{gallery}events/2016-02-18-Sunny-Sport-Day{/gallery}
{gallery}team/members{/gallery}";
preg_match_all('#\{gallery\}([^,]*?)(?:,single=([^,{]+).*?)?\{/gallery\}#',$str,$out);
// Matches array:
var_export($out);
echo "\n\n---\n\n";
// Folders only array:
var_export(array_filter(array_slice($out,1)[0],'strlen'));
echo "\n\n---\n\n";
// Path + Image files array:
foreach($out[2] as $i=>$v){
if($v){
$result[]="{$out[1][$i]}/$v";
}
}
var_export($result);\
Output:
array (
0 =>
array (
0 => '{gallery}events/2016-02-18-Sunny-Sport-Day,single=IMG_0336.jpg,salign=left{/gallery}',
1 => '{gallery}events/2016-02-18-Sunny-Sport-Day{/gallery}',
2 => '{gallery}team/members{/gallery}',
),
1 =>
array (
0 => 'events/2016-02-18-Sunny-Sport-Day',
1 => 'events/2016-02-18-Sunny-Sport-Day',
2 => 'team/members',
),
2 =>
array (
0 => 'IMG_0336.jpg',
1 => '',
2 => '',
),
)
---
// Folders only array:
array (
0 => 'events/2016-02-18-Sunny-Sport-Day',
1 => 'events/2016-02-18-Sunny-Sport-Day',
2 => 'team/members',
)
---
// Path + Image files array:
array (
0 => 'events/2016-02-18-Sunny-Sport-Day/IMG_0336.jpg',
)
something like this?
<?php
$str=getstr();
preg_match_all('/\{gallery\}(.*?)\{\/gallery\}/u',$str,$matches);
$parsed=[];
foreach($matches[1] as $match){
$tmp=[];
$match=explode(',',$match);
foreach($match as $tmp2){
$tmp2=explode("=",$tmp2);
assert(count($tmp2)<=2);
if(count($tmp2)>1){
$tmp[$tmp2[0]]=$tmp2[1];
}else{
$tmp[]=$tmp2[0];
}
}
$parsed[]=$tmp;
}
var_dump($parsed);
function getstr():string{
$str=<<<'STR'
{gallery}events/2016-02-18-Sunny-Sport-Day,single=IMG_0336.jpg,salign=left{/gallery}
Hey there! We had a great day with a tough but funny competition. Our team had a great race and was able to finish in second place.
{gallery}events/2016-02-18-Sunny-Sport-Day{/gallery}
{gallery}team/members{/gallery}
STR;
return $str;
}
$parsed[0][0] contains events/2016-02-18-Sunny-Sport-Day ,
$parsed [0]["single"] contains IMG_0336.jpg
$parsed [0]["salign"] contains left
$parsed[1][0] contains events/2016-02-18-Sunny-Sport-Day
$parsed[2][0] contains team/members
full output of the var_dump is
array(3) {
[0]=>
array(3) {
[0]=>
string(33) "events/2016-02-18-Sunny-Sport-Day"
["single"]=>
string(12) "IMG_0336.jpg"
["salign"]=>
string(4) "left"
}
[1]=>
array(1) {
[0]=>
string(33) "events/2016-02-18-Sunny-Sport-Day"
}
[2]=>
array(1) {
[0]=>
string(12) "team/members"
}
}

PHP regex - weird issue with multiple group capture

The code:
$pattern = '~(/(?P<lang>en|ru))?/foo(/(?P<bar>bar))?~';
preg_match($pattern, '/foo', $matches);
var_dump($matches);
/*output:
array(1) {
[0] =>
string(4) "/foo"
}*/
preg_match($pattern, '/foo/bar', $matches);
var_dump($matches);
/*output:
array(7) {
[0] =>
string(8) "/foo/bar"
[1] =>
string(0) ""
'lang' =>
string(0) ""
[2] =>
string(0) ""
[3] =>
string(4) "/bar"
'bar' =>
string(3) "bar"
[4] =>
string(3) "bar"
}*/
The question: why the hell does it capture <lang> in the second preg_match call and how do I fix it?
P.S. I tried this regex on https://www.regex101.com and there it captures correctly, but on my machine with PHP7, it does not. I get the feeling that regex101 filters the output.
As others have said, that's simply how regex works. It's fairly universal to regexes, as far as I know. It even has parallels in programming in general, such as how Java requires a String returning function to return a String (unless it throws an error).
In PHP, use array_filter on $matches to remove empty entries.
Also, I suggest using non-capturing groups (?:) to cut the clutter:
(?:/(?P<lang>en|ru))?/foo(?:/(?P<bar>bar))?
Or split it into 2 regexes: (?:/(?P<lang>en|ru)) and /foo(?:/(?P<bar>bar)).

PHP String Extraction [duplicate]

This question already has an answer here:
PHP preg_match to find multiple occurrences
(1 answer)
Closed 8 years ago.
I'm weak with regex, need help. My problem is I have to extract all the string that matches the given pattern I have into an array. See the problem below:
The string
<?php
$alert_types = array(
'warning' => array('', __l("Warning!") ),
'error' => array('alert-error', __l("Error!") ),
'success' => array('alert-success', __l("Success!") ),
'info' => array('alert-info', __l("For your information.") ),
);?>
The Preg_Match Code
preg_match("/.*[_][_][l][\(]['\"](.*)['\"][\)].*/", $content, $matches);
I'm only getting the first one match which is Warning!. I'm Expecting matches will have the following values:
Warning!, Error!, Success!, For your information.
Actually I'm using file_get_contents($file) to get the string.
Can anyone help me to solve this. Thankyou in advance.
preg_match() only finds the first match in the string. Use preg_match_all() to get all matches.
preg_match_all("/.*__l\(['\"](.*?)['\"]\).*/", $content, $matches);
$matches[1] will contain an array of the strings you're looking for.
BTW, you don't need all those single-character brackets. Just put the character into the regexp.
var_dump($matches);
array(2) {
[0]=>
array(4) {
[0]=>
string(45) " 'warning' => array('', __l("Warning!") ),"
[1]=>
string(52) " 'error' => array('alert-error', __l("Error!") ),"
[2]=>
string(58) " 'success' => array('alert-success', __l("Success!") ),"
[3]=>
string(65) " 'info' => array('alert-info', __l("For your information.") ),"
}
[1]=>
array(4) {
[0]=>
string(8) "Warning!"
[1]=>
string(6) "Error!"
[2]=>
string(8) "Success!"
[3]=>
string(21) "For your information."
}
}

Add text to each element of array

Basically what I am trying to do is add text before (and after) each element of an array. This is an example:
<?php
$word="code";
$chars=preg_split('//', $word, -1, PREG_SPLIT_NO_EMPTY);
print"<pre>";
print_r($chars);
print"</pre>";
?>
(Yes I need the regex so I can't just use str_split())
which outputs:
Array
(
[0] => c
[1] => o
[2] => d
[3] => e
)
Now my ultimate goal is to get the final string to be something like:
"shift+c","shift+o","shift+d","shift+e"
If I can get help just adding the "shift+ in front of each element, then I can use implode() to do the rest.
Here's a solution based on my comments:
$word = 'code';
$result = array_map(function($c){ return "shift+$c"; }, str_split($word));
And here's the output var_dump($result):
array(4) {
[0]=> string(7) "shift+c"
[1]=> string(7) "shift+o"
[2]=> string(7) "shift+d"
[3]=> string(7) "shift+e"
}
Edit: If you really need to you can use the result from preg_split as the array in array_map.
You can loop through the chars array and concatenate your desired string.
<?php
$word="code";
$chars=preg_split('//', $word, -1, PREG_SPLIT_NO_EMPTY);
foreach($chars as $c){
echo "shift+" . $c . " ";
}
?>
Outputs:
shift+c shift+o shift+d shift+e

Categories