REGEX match two patterns between specific characters - php

I know the title may be a little vague but I wasnt sure how to formulate it. I have a string that contains text that looks something like this:
$data["key1"] = "value1";
$data["key2"] = "value2";
$data["key3"] = "value3";
$data["key4"] = "value4";
I would like to match everything after $data[" and ]" and everything in between = " and "; in the same match, so for example the results would be
Match 1 = {key1, value1}
Match 2 = {key2, value2}
Match 3 = {key3, value3}
Match 4 = {key4, value4}
So far I have been able to match the values with
/(?<=]\s=\s\")(.*?)(?=\s*\"\;)/
but I would also need the first part in the result as well and I'm not sure how to do so.
Also, is there a way to have it match if there is (or isn't) white spaces between characters?
for example
$data["key1"]= "value1";
$data["key2"]="value2";
$data["key3"] ="value3";
$data["key4"] ="value4" ;
Would also all match the same thing?

Try using preg_match_all:
$input = '$data["key1"] = "value1";';
preg_match_all('/\$\w+\["(.*?)"\]\s*=\s*"(.*?)";/', $input, $matches);
echo "Match = {" . $matches[1][0] . ", " . $matches[2][0] . "}";
This prints:
Match = {key1, value1}

You can try the following for each line. Basically you just need to search for each pair of quotes in each line should do the work.
// $output_array is an array which the first index is your key and second is the value
// for example, array( "key1", "value1")
$input_lines = '$data["key1"] = "value1"';
preg_match_all('/\"\w+\"/', $input_lines, $output_array);

Related

How to use regex or preg_match in PHP to extract exact parts of a string as a variables?

echo(addslashes($dataItem->calculation));
Returns:
"if(([item-237_isChecked])){(2350)}
if(([item-238_isChecked])){(3000)}
if(([item-236_isChecked])&&([item-242_isChecked])){(1090)}
if(([item-236_isChecked])&&([item-243_isChecked])){(2860)}
if(([item-239_isChecked])){(4000)}"
$dataItem->calculation comes from the database.
I am trying to extract the values (2350,3000,1090,2860,4000) as separate variables (those values can change, so I want to match anything for example
between
if(([item-237_isChecked])){(
and
")}"
).
Did a bunch of testing, but didn't succeed:
$calculationString1 = preg_match('/if(([item-237_isChecked])){((.*?))}/', addslashes($dataItem->calculation));
UPDATE:
I solved the problem by simplifying my input with explode():
$somestring1 = explode(PHP_EOL, addslashes($dataItem->calculation));
$somesubstring1 = explode('{',$somestring1[0]);
$somesubstring2 = explode('{',$somestring1[1]);
$somesubstring3 = explode('{',$somestring1[2]);
$somesubstring4 = explode('{',$somestring1[3]);
$somesubstring5 = explode('{',$somestring1[4]);
preg_match('/[0-9]{1,6}+/', $somesubstring3[1], $singlelongprice1);
preg_match('/[0-9]{1,6}+/', $somesubstring4[1], $singlewidelongprice1);
preg_match('/[0-9]{1,6}+/', $somesubstring1[1], $doublelongprice1);
preg_match('/[0-9]{1,6}+/', $somesubstring2[1], $triplelongprice1);
preg_match('/[0-9]{1,6}+/', $somesubstring5[1], $quodlongprice1);
$singlelongprice = implode($singlelongprice1);
$singlewidelongprice = implode($singlewidelongprice1);
$doublelongprice = implode($doublelongprice1);
$triplelongprice = implode($triplelongprice1);
$quodlongprice = implode($quodlongprice1);
It looks like isolating your targeted digital strings doesn't require matching the right-side )} so I am omitting that part from my pattern. I am matching {(, then restarting the fullstring match with \K, then matching the consecutive digits.
After checking if preg_match_all() makes exactly 5 matches, I assign the 5 fullstring matches ([0] is the fullstring matches subarray), and assign them to variables using the modern technique of array deconstructing -- this can be replace with the less-modern list() call.
Code: (Demo)
$data = 'if(([item-237_isChecked])){(2350)}
if(([item-238_isChecked])){(3000)}
if(([item-236_isChecked])&&([item-242_isChecked])){(1090)}
if(([item-236_isChecked])&&([item-243_isChecked])){(2860)}
if(([item-239_isChecked])){(4000)};';
[$singlelongprice1, $singlewidelongprice1, $doublelongprice1, $triplelongprice1, $quadlongprice1] = preg_match_all('~{\(\K\d+~', $data, $matches) == 5 ? $matches[0] : ['','','','',''];
echo '$singlelongprice1 = ' , $singlelongprice1 , "\n";
echo '$singlewidelongprice1 = ' , $singlewidelongprice1 , "\n";
echo '$doublelongprice1 = ' , $doublelongprice1 , "\n";
echo '$triplelongprice1 = ' , $triplelongprice1 , "\n";
echo '$quadlongprice1 = ' , $quadlongprice1;
Output:
$singlelongprice1 = 2350
$singlewidelongprice1 = 3000
$doublelongprice1 = 1090
$triplelongprice1 = 2860
$quadlongprice1 = 4000
p.s. I changed quod to quad. Whenever you need to develop a regex pattern, run your tests # https://regex101.com like this: https://regex101.com/r/31pNLa/1

How to check specyfic url_path in preg_match

How can I check if specific path match to pattern.
Example:
I have a path with one or more unknown variable
$pathPattern = 'user/?/stats';
And let say I received this path
$receivedPath = 'user/12/stats'
So, how can I check if that received path match to my pattern?
I tried to do something like below but didn't work.
$pathPattern = 'user/?/stats';
$receivedPath = 'user/12/stats';
$pathPatternReg = str_replace('?','.*',$pathPattern);
echo preg_match('/$pathPatternReg/', $receivedPath);
Thank you.
Regex should be something like this for a unknown user\/[0-9]+\/stats
And Could be used as such;
if(preg_match("user\/[0-9]+\/stats",$variable)) { .... }
As stated by Tom, you possibly have to escape the '/' characters with a '\'.
You only want to match one specific part of your total query string, the number in the center. Most regex interpreters provide this functionality in form of round brackets, like this:
$pattern = "user\/([0-9]+)\/stats";
Notice the round brackets around the [0-9]+ : it tells preg_match to store this part of the matched pattern in the $matches array.
So, your code could look like this:
$subject = "user/12/stats";
$pattern = "user\/([0-9]+)\/stats";
$matches = array();
if( preg_match($pattern, $subject, $matches) ){
// there was a match
// The $matches array now looks like this:
// { "user/12/stats", "12" }
// { <whole matched string>, <string in first parenthesis>, .... }
$user_id = $matches[1]
...
}
(not tested)
See also here: https://secure.php.net/manual/en/function.preg-match.php
Thank you booth.
This is a solution:
$pathPattern = 'user/?/stats';
$receivedPath = 'user/12/stats';
$pathPatternReg = str_replace(['/','?'],['\/','.*'],$pathPattern);
$pattern = "/^$uri/";
echo preg_match($pattern, $receivedPath);

Search and replace all lines in a multiline string

I have a string with a large list with items named as follows:
str = "f05cmdi-test1-name1
f06dmdi-test2-name2";
So the first 4 characters are random characters. And I would like to have an output like this:
'mdi-test1-name1',
'mdi-test2-name2',
As you can see the first characters from the string needs to be replaced with a ' and every line needs to end with ',
How can I change the above string into the string below? I've tried for ours with 'strstr' and 'str_replace' but I can't get it working. It would save me a lot of time if I got it work.
Thanks for your help guys!
Here is a way to do the job:
$input = "f05cmdi-test1-name1
f05cmdi-test2-name2";
$result = preg_replace("/.{4}(\S+)/", "'$1',", $input);
echo $result;
Where \S stands for a NON space character.
EDIT : I deleted the above since the following method is better and more reliable and can be used for any possible combination of four characters.
So what do I do if there are a million different possibillites as starting characters ?
In your specific example I see that the only space is in between the full strings (full string = "f05cmdi-test1-name1" )
So:
str = "f05cmdi-test1-name1 f06dmdi-test2-name2";
$result_array = [];
// Split at the spaces
$result = explode(" ", $str);
foreach($result as $item) {
// If four random chars take string after the first four random chars
$item = substr($item, 5);
$result_array = array_push($result_arrray, $item);
}
Resulting in:
$result_array = [
"mdi-test1-name1",
"mdi-test2-name2",
"....."
];
IF you would like a single string in the style of :
"'mdi-test1-name1','mdi-test2-name2','...'"
Then you can simply do the following:
$result_final = "'" . implode("','" , $result_array) . "'";
This is doable in a rather simple regex pattern
<?php
$str = "f05cmdi-test1-name1
f05cmdi-test2-name2";
$str = preg_replace("~[a-z0-9]{1,4}mdi-test([0-9]+-[a-z0-9]+)~", "'mdi-test\\1',", $str);
echo $str;
Alter to your more specific needs

Regular Expressions to replace {{a,b}} and {{a}}

I have many strings. Some examples are shown below:
This is my first example string. {{1}} This is what it looks like.
This is my second example string. {{1,2}}. This is what it looks like.
This is my third example string. {{1,3}} and {{2}}. This is what it looks like.
My code needs to replace each token that looks like {{1}} with <input name="var1">
It also needs to replace each token that looks like {{1,2}} with <input name="var1" value="2">
In general, each token that looks like {{a}} needs to be replaced with <input name="vara"> and each token that looks like {{a,b}} with <input name="vara" value="b">
I am using php.
What would be the best way to do this. There will be many "tokens" to replace within each string. And each string can have tokens of both styles.
Right now, my code looks like this:
for ($y = 1; $y < Config::get('constants.max_input_variables'); $y++) {
$main_body = str_replace("{{" . $y . "}}", "<input size=\"5\" class=\"question-input\" type=\"text\" name=\"var" . $y . "\" value=\"".old('var'.$y)."\" >", $main_body);
}
But this is obviously not very efficient since I cycle through looking for matches. And ofcourse, I am not even matching the tokens that look like {{1,2}}
Use regex \{\{(\d+)(,(\d+))?\}\}
Regex Explanation and Live Demo
\{: Matches { literally, need to escape as it is special symbol in regex
(\d+): Matches one or more digits, captured in group 1
(,(\d+))?: Matches one or more digits followed by comma optionally
\}: Matches } literally
$1 and $3 are used in the replacement to get the first and third captured group respectively.
Example Code Usage:
$re = "/\\{\\{(\\d+)(,(\\d+))?\\}\\}/mi";
$str = "This is my first example string. {{1}} This is what it looks like.\nThis is my second example string. {{1,2}}. This is what it looks like.\nThis is my third example string. {{1,3}} and {{2}}. This is what it looks like.";
$subst = "<input name=\"var$1\" value=\"$3\" />";
$result = preg_replace($re, $subst, $str);
You need to use a callback:
$str = preg_replace_callback('/{{([^},]+)(?:,([^}]+))?}}/', function($_) {
return '<input name="var'.$_[1].'"' . (isset($_[2]) ? ' value="'.$_[2]. '"' : '') . '>';
}, $str);
See demo at eval.in
The regex {{([^},]+)(?:,([^}]+))?}} can be tried at regex101. Negated class [^},] matches characters that neither } nor ,. + one ore more. The second part (?:,([^}]+))? is optional.
you can use str_replace to get the number.
$str = str_replace(array('{{', '}}'), '' , '{{12,13}}');
output $str:
$str = '12,13';
then, use $arr = explode(',', $str), you can get the two number: 12 and 13
so the <input>. just use $arr[0] to fill in name and $arr[1] to fill in value.
the all codes:
$str = str_replace(array('{{', '}}'), '' , '{{12,13}}');
$arr = explode(',', str);
return '<input name="var'.$arr[0].'" value="'.$arr[1].'" />';

REGEX: replacing everything between two strings, but not the start/end strings

I am not the best with RegEx... I have some PHP code:
$pattern = '/activeAds = \[(.*?)\]/si';
$modData = preg_replace($pattern,'TEST',$data);
So I have a JavaScript file, and it declares and array:
var activeAds = [];
I need this to populate the array with my string, or if the array already has a string inside it, i want to replace it with my string (in this case "TEST").
Right now, my REGEX is replacing everything, including my start and end, i need to only replace whats between.
I'm left with:
var TEST;
TIA
You could capture what's before and what's after the part you want replacing:
$pattern = '/(activeAds = \[).*?(\])/si';
After capturing these parts, you can keep them and replace the part in the middle:
$modData = preg_replace($pattern, '\1TEST\2', $data);
There are many ways you could do this, mine is below:
$data = array("activeAds = testing123");
$pattern = "/activeAds\s?=\s?(.*)/";
$result = preg_replace($pattern,"activeAds = TEST", $data);
var_dump($result);
Edit: Forgot to mention that the \s? here allow for an optional space.

Categories