Regular expression - repeat groups - php

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.

Related

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

PHP - Preg_match_all optional match

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][*]"
}
}

issues using memberOf clause in ldap query

I'm trying to accomplish something very similar to what this user was doing Here.
I followed the answer, but I could not get it working. Inside the Active directory, my memberOf field looks like this:
CN=$VPN Users,CN=Users,DC=iai,DC=pri,CN=$ITAR,CN=Users,DC=iai,DC=pri,CN=allsubscribers,CN=Users,DC=iai,DC=pri
My Filter that works is:
(&(objectCategory=person)(sAMAccountName=$p_username))
I'm trying to get the following to work:
(&(objectCategory=person)(sAMAccountName=$p_username)(memberOf=CN=$ITAR))
I have tried adding the full DN which is
CN=Users,DC=iai,DC=pri
to my filter as well, but I get:
array(1) { ["count"]=> int(0) }
as my response.
I'm using ldap 3
This is the partial Working authentication code written in php:
$login = ldap_bind( $url, "username#somedomain", $password );
$attributes = array("displayname", "mailnickname");
$filter = "(&(objectCategory=person)(sAMAccountName=$username))";
$result = ldap_search($url, "CN=Users,DC=iai,DC=pri", $filter, $attributes);
$entries = ldap_get_entries($url, $result);
What am I doing wrong?
Code Result From #DaveRandom
First Var dump:
string(49) "(&(objectCategory=person)(sAMAccountName=rmoser))"
array(2) {
["count"] => int(1)
[0] => array(8) {
["displayname"] => array(2) {
["count"] => int(1)
[0] => string(10) "Ryan Moser"
}
[0] => string(11) "displayname"
["memberof"] => array(4) {
["count"] => int(3)
[0] => string(36) "CN=$VPN Users,CN=Users,DC=iai,DC=pri"
[1] => string(31) "CN=$ITAR,CN=Users,DC=iai,DC=pri"
[2] => string(40) "CN=allsubscribers,CN=Users,DC=iai,DC=pri"
}
[1]=> string(8) "memberof"
["mailnickname"] => array(2) {
["count"] => int(1)
[0] => string(6) "rmoser"
}
[2] => string(12) "mailnickname"
["count"] => int(3)
["dn"] => string(36) "CN=Ryan Moser,CN=Users,DC=iai,DC=pri"
}
}
bool(false)
Second var_dump:
string(70) "(&(objectCategory=person)(sAMAccountName=rmoser)(memberof=*CN=$ITAR*))"
array(1) {
["count"] => int(0)
}
LDAP filters look for an exact match.
In order to match CN=$ITAR anywhere in a value, you will need to surround it with the filter wildcard character *.
Try this filter:
(&(objectCategory=person)(sAMAccountName=$p_username)(memberOf=*CN=$ITAR*))
Also don't forget that $ITAR is a valid variable name in PHP, so if you place that filter string in double quotes (which you would need to in order for $p_username to be interpolated) PHP will attempt to interpolate $ITAR as a variable as well, find that it (probably) doesn't exist and the end result will be that it gets stripped from the string.
$filter = "(&(objectCategory=person)(sAMAccountName=$p_username)(memberOf=*CN=\$ITAR*))";
A useful link for any question concerning a dynamic filter built with PHP is this.

Categories