How to write a regex pattern which matches following Array? - php

I want to write a regex pattern that user enters values matches the any one of the index in the following array ,can you please help me to achieve this thing...
$cars=['bmw','Audi','Ferari','BenZ',];
$regex_pattern=^[A-Za-z]+(?: [A-Za-z]+)*$; //it takes the value only string with space or without space,now i want to match the pattern with the given array values .
if(preg_match($regex_pattern,$request->search)){
my logic
}
InvalidScenarios:
Flight
Ship
Valid-Scenarios:
bmw
Audi
Ferari
Benz

$cars=['bmw','Audi','Ferari','BenZ',];
$regex_pattern=^[A-Za-z ]+$; //it takes the value only string with space or without space,now i want to match the pattern with the given array values .
if(preg_match($regex_pattern,$request->search)){
my logic
}

you can use
$matches = preg_grep ('/^ship (\w+)/i', $cars);
Output : []
$matches = preg_grep ('/^bmw (\w+)/i', $cars);
Output : [ 0 => 'bmw' ];
It will return array of values matched.
You can check for $matches if it is an empty array that means you don't have any match.
Reference : https://www.php.net/manual/en/function.preg-grep.php

You could write a dynamic pattern to assert for the word in the string, and then use your regex to match only the allowed characters.
$cars=['bmw','Audi','Ferari','BenZ'];
$str = 'bmw
Audi
Ferari
Benz
Flight
Ship';
$regex_pattern = sprintf
("/^(?=.*\b(?:%s)\b)[A-Za-z]+(?: [A-Za-z]+)*$/im",
implode('|', $cars)
);
preg_match_all($regex_pattern, $str, $matches);
var_dump($matches[0]);
Output
array(4) {
[0]=>
string(3) "bmw"
[1]=>
string(4) "Audi"
[2]=>
string(6) "Ferari"
[3]=>
string(4) "Benz"
}

Related

preg_match_all : Assign same name to two subpatterns

I want to use a regex to match two different subpatterns and give them the same name using the PCRE_INFO_JCHANGED modifier (?J)
The two subpatterns are very different from each other so I have to catch them using |
What I usually do is give the two patterns a different name and then choose the one I want using PHP, but I'd like to know if it possible without PHP
Example here : https://3v4l.org/GEMeT (edited thanks to #JustOnUnderMillions)
The 2nd ?P<number> will always capture and replace the first ?P<number>
What I want : Capture both patterns with one regex and store them both with the same key number
Desired output :
Pattern 1
string(1) "1"
Pattern 2
string(1) "2"
Thanks for your help !
Dont use preg_match_all here
$regex = '/(?J)I wanna match pattern (?P<number>1) which is very different from pattern 2|(?P<number>2), again nothing to do with pattern 1 here/';
Result with preg_match:
array(3) {
[0]=>
string(62) "I wanna match pattern 1 which is very different from pattern 2"
["number"]=>
string(1) "1"
[1]=>
string(1) "1"
}
Full with fixed regex 'nothing similar' was not found in the orignal regex:
$text1 = 'I wanna match pattern 1 which is very different from pattern 2';
$text2 = 'I wanna match pattern 2, again nothing similar with pattern 1 here';
$regex = '/(?J)(I wanna match pattern (?P<number>1) which is very different from pattern 2|I wanna match pattern (?P<number>2), again nothing similar with pattern 1 here)/';
echo "Pattern 1\n";
preg_match( $regex, $text1, $matches );
var_dump($matches);
echo "\n\nPattern 2\n";
preg_match( $regex, $text2, $matches );
var_dump($matches);

PHP: How to split a string in substrings that match and don't match a regex pattern?

I'm new here and need your help. I want to match an string that is an URI - and get an array of substrings.
This is my input string:
/part-of-{INTERESETINGSTUFF}/an-url/{MORESTUFF}
I want this output array:
array(4) {
[0]=>
string(9) "/part-of-"
[1]=>
string(19) "{INTERESETINGSTUFF}"
[2]=>
string(8) "/an-url/"
[3]=>
string(11) "{MORESTUFF}"
}
I'm already able to preg_match everything with curly brackets by the pattern \{[^}]+\}. But how can I achieve my desired result?
Best regards!
What about this. See on regex101
\/.*?(?={|\/)\/?|{.*?}
Then store the matches in an array.
\/.*? matches all character following /
(?={|\/) stops match if next character is { or /
\/? match optional / at the end of match
{.*?} matches brackets and everything between
You can use a very simple ({[^{}]*}) regex matching {, zero or more symbols other than { and } with preg_split and PREG_SPLIT_DELIM_CAPTURE option (that will put all the captured subvalues into the resulting array):
$str = '/part-of-{INTERESETINGSTUFF}/an-url/{MORESTUFF}';
$res = array_filter(preg_split('/({[^{}]*})/', $str, -1, PREG_SPLIT_DELIM_CAPTURE));
print_r($res);
// => Array( [0] => /part-of- [1] => {INTERESETINGSTUFF} [2] => /an-url/ [3] => {MORESTUFF} )
See PHP demo
The array_filter is used to remove all empty elements from the resulting array.

split by special char and remove empty elements in php and javascript array

I have a merged string merged by numbers and each number element has the & character in the beginning and end.
Actual string &1&&3&&5&
If you add 6 to this string the final string will be &1&&3&&5&&6&
The problem is when I want to get numbers in this string of arrays, too many empty element in the array also I don't need them.
When I split explode(',', actualstr) the array is ["1","","3","","5","","6"] but I need this ["1","3","5","6"]
I will do this many times so need most efficient way.
There is a similar scenario in js too if there is special way need to know, if not it's ok with manual check.
Remove the leading and trailing &, then explode by double &&.
$array = explode('&&',trim($str,'&'));
print_r($array);
Array
(
[0] => 1
[1] => 3
[2] => 5
[3] => 6
)
One quickfix to that is using regex, but only if you know and are 100% about the data you are working with
preg_match_all("/[0-9]/", "&1&&3&&5&&6&", $numbers);
var_dump($numbers);
array(1) {
[0]=>
array(4) {
[0]=>
string(1) "1"
[1]=>
string(1) "3"
[2]=>
string(1) "5"
[3]=>
string(1) "6"
}
}
Another way would be to use array filter, if the data between the '&' is not fit for filtering by regex
array_filter(explode("&", "&1&&3&&5&&6&"))
You can use trim() function to remove a spacial character or removing space character from the string.
$str = "&1&&3&&5&&6&";
$str_clear = trim($str, '&');
$array = explode('&&',$str_clear);
print_r($array);
I don't know how you extract the number of this string, but if you do like this you can get an array of the numbers:
preg_match_all('/&([0-9])&/','&1&&3&&5&',$matches);
var_dump($matches);
In JavaScript you can do something like #AlexAndrei has done in PHP:
var str='&1&&3&&5&';
var result=str.substr(0,str.length-1).substr(1).split('&&');
console.log(result);
I think this is what you're trying to do.
$str = "&1&&3&&5&&6&";
$numArray = preg_split('/&/', $str, -1, PREG_SPLIT_NO_EMPTY);
print_r($numArray);

Why is preg_match_all returning two matches?

I am trying to identify if a string has any words between double quotes using preg_match_all, however it's duplicating results and the first result has two sets of double quotes either side, where as the string being searched only has the one set.
Here is my code:
$str = 'Test start. "Test match this". Test end.';
$groups = array();
preg_match_all('/"([^"]+)"/', $str, $groups);
var_dump($groups);
And the var dump produces:
array(2) {
[0]=>
array(1) {
[0]=>
string(17) ""Test match this""
}
[1]=>
array(1) {
[0]=>
string(15) "Test match this"
}
}
As you can see the first array is wrong, why is preg_match_all returning this?
It returns 2 elements because:
Element 0 captures the whole matched string
Elements 1..N capture dedicated matches.
PS: another way of expressing the same could be
(?<=")[^"]+(?=")
which would capture exactly the same but in that case you don't need additional capturing group.
Demo: http://regex101.com/r/lF3kP7/1
Hi if your are using print_r instead of vardump you will see the differences in a better way.
Array
(
[0] => Array
(
[0] => "Test match this"
)
[1] => Array
(
[0] => Test match this
)
)
The first contains whole string and the second is your match.
Remove the parenthesis.
you can write the pattern as '/"[^"]+"/'
This is because you're using group matching. take the parentheses out of your pattern and you'll get one array back. Something like:
preg_match_all('/\"[^"]+\"/', $str, $groups);

Re-order regular expression matches

Is there a way to get the match patterns to change order? For example if you have a string with letters-digits and using preg_match_all(), and you want the resulting match array to have the digits before the letters. Is there a way to specify this in the regular expression itself?
So "aaa-111" would result in matches with
array(0 => '111', 1 => 'aaa');
Perhaps named capture groups will help. Example:
preg_match('/(?<alphapart>[a-z]+)-(?<numpart>[0-9]+)/', 'aaa-111', $matches);
$matches:
array('alphapart' => 'asd', 'numpart' => '111')
This way you can refer to the matches by a name instead of whatever order index they were matched in.
Edit: Just for accuracy, I want to note that $matches will actually include the matches by index as well, so the actual $matches will be: array(5) { [0]=> string(7) "aaa-111" ["alphapart"]=> string(3) "aaa" [1]=> string(3) "aaa" ["numpart"]=> string(3) "111" [2]=> string(3) "111" }
The order of groups in a regex is dependent on their positions in the regex and the string. Changing the order would make it very confusing.
What you can do is use "named groups".
/(?P<letters>\w*)-(?P<digits>\d*)/
The array will still be in the same order, but, you can use $matches['digits'] to easily get just the digits.
DEMO: http://ideone.com/3tRJLZ
Yes you can. You can use lookaheads that don't push the 'cursor' and so you could first match the last part, and then the first part. It works with (?=regex)
This works:
(?=\w+\-(\d+))(\w+)\-\d+
but will also give the full match at index 0. Like ["aaa-111", "111", "aaa"]
is that a problem?
I don't believe there is. Regex isn't designed to sort. You could setup two different regular expressions to check for each pattern though. This code will echo the two string in num/alpha order as you requested:
<?php
header('Content-Type: text/plain');
$string1 = 'aaa-123';
$string2 = '123-aaa';
echo 'String 1: '.$string1."\n";
echo 'String 2: '.$string2."\n";
$pattern1 = '/([\d]+)-([a-z]+)/i';
$pattern2 = '/([a-z]+)-([\d]+)/i';
echo 'Result 1: ';
if(preg_match($pattern1, $string1, $matches))
{
echo $matches[1].' '.$matches[2]."\n";
}
if(preg_match($pattern2, $string1, $matches))
{
echo $matches[2].' '.$matches[1]."\n";
}
echo 'Result 2: ';
if(preg_match($pattern1, $string2, $matches))
{
echo $matches[1].' '.$matches[2]."\n";
}
if(preg_match($pattern2, $string2, $matches))
{
echo $matches[2].' '.$matches[1]."\n";
}
?>
The resulting output is:
String 1: aaa-123
String 2: 123-aaa
Result 1: 123 aaa
Result 2: 123 aaa
If you want the digits to be there first, you need to sort the array yourself.
array_sort() will... sort it out for you.

Categories