Regex match from right to left - php

I wanted to match something from right to left, below is one of such example.
100abababab3x3x3xx1000morewords
If i want to match something between and last xx and immediate previous ab and get 3x3x3
I tried something like below , but it matches ababab3x3x3
preg_match('/ab(.*?)xx/',$text,$totmat);
Note : please don't recommend strrev.
Above example is just for illustration , all i wanted to do is match from right to left.

Not sure this is the most optimized way or not? But this will work for you if you use the combination of Look ahead positive (?=) and Look behind positive (?<=). See regex
<?php
$re = '/\w+(?<=ab)(.*?)(?=xx)/m';
$str = '100abababab3x3x3xx1000morewords';
preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0);
// Print the full matched result
echo $matches[0][1];
DEMO: https://3v4l.org/db69N

$str = '100abababab3x3x3xx1000morewords';
preg_match('/ab((?:(?!ab).)*)xx/', $str, $m);
print_r($m);
Output:
Array
(
[0] => ab3x3x3xx
[1] => 3x3x3
)
>Explanation:
ab : literally ab
( : start group 1
(?: : start non capture group
(?!ab) : negative lookahead, make sure we doon't have ab
. : any character but newline
)* : end group, may appear 0 or more times
) : end group 1
xx : literally xx

There are other approaches than a regex to this kind of problem that would be close to twice faster in computing time.
Here for example :
$str = "100abababab3x3x3xx1000morewords";
$result = explode("ab", explode("xx", $str)[0]);
var_dump(end($result));
First occurence of explode split the string in two between the "xx" characters. We're only interested by the left part (Index 0).
Second occurence of explode split the string with the caracters ab. We're only interested by the last occurence of ab. Therefore var_dump(end($result)); prints the expected result.

Related

regex inside tags with specified string

I'm not very good at regex but i have a string like this :
$str = '<span id="MainStatuSSpan" style="background: brown;"> Incoming: 012345678 Group- SUPERMONEY Fronter: - 992236 UID: Y3281602190002004448</span>';
$pattern = '/(?:Fronter: - )[0-9]{1,6}/i';
preg_match($pattern, $str, $matches);
print_r($matches);
/*** ^^^^^^^ This prints :*/
Array ( [0] => Fronter: - 992236 )
In case of the Fronter is not with - or spaces I don't get the Fronter - number.
Can anyone help with an example that works in any case, there is always a Fronter and a number.
you can use Fronter:\W*[0-9]{1,6}
Fronter:\W*[0-9]{1,6} : match Fronter:
\W* : zero or more non-word characters
[0-9]{1,6} one to six digits
you regex will also find a match with Fronter:99222236 so you must use \b to avoid overflow digit length
Fronter:[- ]*[0-9]{1,6}\b

PHP: Regular exp to get the last number from exactly string

I'm trying to get the string that match with original and with number in the end.
I got these strings:
mod_courts2
mod_courts_config
mod_courts_config2
From these strings I want the one that matches only with "mod_courts" with number in the end.
I'm doing this:
if (strpos($t, "mod_courts") !== FALSE) {
preg_match('/^\w+(\d+)$/U', $t, $match);
echo $match;
}
This returns me "mod_courts2" and "mod_courts_config2", I just want "mod_courts2"
Use the following regex:
/^[a-z]+_[a-z]+(\d+)$/
Explanation:
^ - assert position at the beginning of the string
[a-z]+ - match any alphabet one or more times
_ - match a literal undescore character
[a-z]+ - match any alphabet one or more times
(\d+) - match (and capture) any digit from 0 to 9 one or more times
$ - assert position at the end of the string
Test cases:
$array = array(
'mod_courts2',
'mod_courts_config',
'mod_courts_config2'
);
foreach ($array as $string) {
if(preg_match('/^[a-z]+_[a-z]+(\d+)$/i', $string, $matches)) {
print_r($matches);
}
}
Output:
Array
(
[0] => mod_courts2
[1] => 2
)
Very simply, you can do:
/^(mod_courts\d+)$/
However, if you want exactly the following format: sometext_somettext2, you can use the following regex:
/^([a-zA-Z]+_[a-zA-Z]+\d+)$/
or
/^([^_]+_[^_]+\d+)$/
Demos
http://regex101.com/r/jP8iC1
http://regex101.com/r/tI1uX8
http://regex101.com/r/fX8pO5
^mod_courts\d+$
this should do it
You can just use
^mod_courts[0-9]+$
Meaning mod_courts followed by a number (and only that, thanks to ^$ matching the beginning and end of the string). No need for the strpos check.

Split string with regular expressions

I have this string:
EXAMPLE|abcd|[!PAGE|title]
I want to split it like this:
Array
(
[0] => EXAMPLE
[1] => abcd
[2] => [!PAGE|title]
)
How to do it?
Thank you.
DEMO
If you don't need anything more than you said, is like parsing a CSV but with | as separator and [ as " so: (\[.*?\]+|[^\|]+)(?=\||$) will do the work I think.
EDIT: Changed the regex, now it accepts strings like [asdf]].[]asf]
Explanation:
(\[.*?\]+|[^\|]+) -> This one is divided in 2 parts: (will match 1.1 or 1.2)
1.1 \[.*?\]+ -> Match everything between [ and ]
1.2 [^\|]+ -> Will match everything that is enclosed by |
(?=\||$) -> This will tell the regular expression that next to that must be a | or the end of the string so that will tell the regex to accept strings like the earlier example.
Given your example, you could use (\[.*?\]|[^|]+).
preg_match_all("#(\[.*?\]|[^|]+)#", "EXAMPLE|abcd|[!PAGE|title]", $matches);
print_r($matches[0]);
// output:
Array
(
[0] => EXAMPLE
[1] => abcd
[2] => [!PAGE|title]
)
use this regex (?<=\||^)(((\[.*\|?.*\])|(.+?)))(?=\||$)
(?<=\||^) Positive LookBehind
1st alternative: \|Literal `|`
2nd alternative: ^Start of string
1st Capturing group (((\[.*\|?.*\])|(.+?)))
2nd Capturing group ((\[.*\|?.*\])|(.+?))
1st alternative: (\[.*\|?.*\])
3rd Capturing group (\[.*\|?.*\])
\[ Literal `[`
. infinite to 0 times Any character (except newline)
\| 1 to 0 times Literal `|`
. infinite to 0 times Any character (except newline)
\] Literal `]`
2nd alternative: (.+?)
4th Capturing group (.+?)
. 1 to infinite times [lazy] Any character (except newline)
(?=\||$) Positive LookAhead
1st alternative: \|Literal `|`
2nd alternative: $End of string
g modifier: global. All matches (don't return on first match)
A Non-regex solution:
$str = str_replace('[', ']', "EXAMPLE|abcd|[!PAGE|title]");
$arr = str_getcsv ($str, '|', ']')
If you expect things like this "[[]]", you would've to escape the inside brackets with slashes in which case regex might be the better option.
http://de2.php.net/manual/en/function.explode.php
$array= explode('|', $string);

How do i break string into words at the position of number

I have some string data with alphanumeric value. like us01name, phc01name and other i.e alphabates + number + alphabates.
i would like to get first alphabates + number in first string and remaining on second.
How can i do it in php?
You can use a regular expression:
// if statement checks there's at least one match
if(preg_match('/([A-z]+[0-9]+)([A-z]+)/', $string, $matches) > 0){
$firstbit = $matches[1];
$nextbit = $matches[2];
}
Just to break the regular expression down into parts so you know what each bit does:
( Begin group 1
[A-z]+ As many alphabet characters as there are (case agnostic)
[0-9]+ As many numbers as there are
) End group 1
( Begin group 2
[A-z]+ As many alphabet characters as there are (case agnostic)
) End group 2
Try this code:
preg_match('~([^\d]+\d+)(.*)~', "us01name", $m);
var_dump($m[1]); // 1st string + number
var_dump($m[2]); // 2nd string
OUTPUT
string(4) "us01"
string(4) "name"
Even this more restrictive regex will also work for you:
preg_match('~([A-Z]+\d+)([A-Z]+)~i', "us01name", $m);
You could use preg_split on the digits with the pattern capture flag. It returns all pieces, so you'd have to put them back together. However, in my opinion is more intuitive and flexible than a complete pattern regex. Plus, preg_split() is underused :)
Code:
$str = 'user01jason';
$pieces = preg_split('/(\d+)/', $str, -1, PREG_SPLIT_DELIM_CAPTURE);
print_r($pieces);
Output:
Array
(
[0] => user
[1] => 01
[2] => jason
)

split on several chars and include them in the parts

I want to split a string on several chars (being +, ~, > and #, but I want those chars to be part of the returned parts.
I tried:
$parts = preg_split('/\+|>|~|#/', $input, PREG_SPLIT_DELIM_CAPTURE);
The result is only 2 parts where there should be 5 and the split-char isn't part of part [1].
I also tried:
$parts = preg_split('/\+|>|~|#/', $input, PREG_SPLIT_OFFSET_CAPTURE);
The result is then 1 part too few (4 instead of 5) and the last part contains a split-char.
Without flags in preg_split, the result is almost perfect (as many parts as there should be) but all the split-chars are gone.
Example:
$input = 'oele>boele#4 + key:type:id + *~the end'; // spaces should be ignored
$output /* should be: */
array( 'oele', '>boele', ' #4 ', '+ key:type:id ', '+ *', '~the end' );
Is there a spl function or flag to do this or do I have to make one myself =(
$parts = preg_split('/(?=[+>~#])/', $input);
See it
Since you want to have the delimiters to be part of the next split piece, your split point is right before the delimiter and this can be easily done using positive look ahead.
(?= : Start of positive lookahead
[+>~#] : character class to match any of your delimiters.
) : End of look ahead assertion.
Effectively you are asking preg_split to split the input string at points just before delimiters.
You're missing an assignment for the limit parameter which is why it's returning less than you expected, try:
$parts = preg_split('/\+|>|~|#/', $input, -1, PREG_SPLIT_OFFSET_CAPTURE);
well i had the same problem in the past. You have to parenthese your regexp with brackets and then it hopefully works
$parts = preg_split('/(\+|>|~|#)/', $input, PREG_SPLIT_OFFSET_CAPTURE);
and here is it explained: http://www.php.net/manual/en/function.preg-split.php#94238
Ben is correct.
Just to add to his answer, PREG_SPLIT_DELIM_CAPTURE is a constant with value of 2 so you get 2 splits, similarly PREG_SPLIT_OFFSET_CAPTURE has a value of 4.

Categories