Facing issue with parse_str(), Replacing + char to space - php

I have the following string url:
HostName=MyHostName;SharedAccessKeyName=SOMETHING;SharedAccessKey=VALUE+VALUE=
I need to extract the key-value pair in an array. I have used parse_str() in PHP below is my code:
<?php
$arr = array();
$str = "HostName=MyHostName&SharedAccessKeyName=SOMETHING&SharedAccessKey=VALUE+VALUE=";
parse_str($str,$arr);
var_dump($arr);
output:
array (
'HostName' => 'MyHostName',
'SharedAccessKeyName' => 'SOMETHING',
'SharedAccessKey' => 'VALUE VALUE=',
)
you can see in the SharedAccessKey char + is replaced by space for this issue, I referred the Similiar Question, Marked answer is not the correct one according to the OP scenario, This says that first do urlencode() and then pass it because parse_str() first decode URL then separate the key-values but this will return array object of a single array which return the whole string as it is like for my case its output is like:
Array
(
[HostName=MyHostName&SharedAccessKeyName=SOMETHING&SharedAccessKey=VALUE+VALUE=] =>
)
Please help me out, not for only + char rather for all the characters should come same as they by the parse_str()

You could try emulating parse_str with preg_match_all:
preg_match_all('/(?:^|\G)(\w+)=([^&]+)(?:&|$)/', $str, $matches);
print_r(array_combine($matches[1], $matches[2]));
Output:
Array (
[HostName] => MyHostName
[SharedAccessKeyName] => SOMETHING
[SharedAccessKey] => VALUE+VALUE=
)
Demo on 3v4l.org

$str = "HostName=MyHostName&SharedAccessKeyName=SOMETHING&SharedAccessKey=VALUE+VALUE=";
preg_match_all('/(?:^|G)(w+)=([^&]+)(?:&|$)/', $str, $matches);
print_r(array_combine($matches[1], $matches[2]));

Related

How do I capture all the numeric substrings from the string?

My string looks like below:
Response: 311768560
311768562
311768564
I have tried:
$success_pattern="Response: ((\d+)[\n])*";
$response="Response: 311768560\n311768562\n311768564\n311768566";
preg_match("/$success_pattern/i", $response, $match);
Output:
Array (
[0] => Response: 311768560 311768562 311768564
[1] => 311768564
[2] => 311768564
)
I need an array containing all the numbers as output like:
array('311768560','311768562','311768564');
<?php
$string="Response: 311768560 311768562 311768564";
preg_match_all("/[\d]+/", $string, $matches);
print_r($matches);
Output:
Array
(
[0] => Array
(
[0] => 311768560
[1] => 311768562
[2] => 311768564
)
)
Try not to get too hung up on a specific function like preg_match(). PHP offers several ways to generate your desired output. I'll show you three different approaches:
Input:
$response = "Response: 311768560
311768562
311768564";
Method #1: explode() with substr() and strpos() (Demo)
$array = explode("\r\n", substr($response, strpos($response, ' ') + 1));
*note, this method assumes that the first string (Response ) is the only unwanted substring and that it is always first. Also, the \r may not be necessary depending on your coding environment. This is probably the fastest of my list of methods because it doesn't use regex, but it does require 3 function calls and one incrementation -- not to mention it may be too literal for your actual use case.
Method #2: preg_match_all() (Demo)
$array = preg_match_all('/\d+/', $response, $out) ? $out[0] : [];
This method is very direct, fast, and requires minimal code. If there are any drawbacks at all, they are that the preg_match_all() returns a true|false result and generates an output variable in the form of a multidimensional array. To modify this output to suit your one-dimensional requirement, I place an inline condition at the end of the function which delivers the desired data to $array.
Method #3: preg_split() (Demo)
$array = preg_split('/\D+/', $response, 0, PREG_SPLIT_NO_EMPTY);
This function behaves just like explode() except it wields the power of regex. The pattern identifies all non-digital substrings and uses them as "delimiters" and splits the string on each of them. For your input, the first delimiter is "Response: ", then the newline character(s) after: "311768560" and "311768562". The beauty of preg_split() is that it directly provides the one-dimensional array that you are seeking.
Output:
No matter which of the above methods you try, you will receive the same correct output: $array = array('311768560', '311768562', '311768564');
If any of these methods fail your actual use case, then it is probably the product of your $response string being too different from the sample data that you have posted here.
Use Array_shift() function
<?php
$str = "Response: 311768560 311768562 311768564";
$s = explode(" ",$str);
$p = array_shift($s);
print_r($s);
?>
output
Array (
[0] => 311768560
[1] => 311768562
[2] => 311768564 )

How to split a string into an array using a given regex expression

I am trying to explode / preg_split a string so that I get an array of all the values that are enclosed in ( ). I've tried the following code but I always get an empty array, I have tried many things but I cant seem to do it right
Could anyone spot what am I missing to get my desired output?
$pattern = "/^\(.*\)$/";
$string = "(y3,x3),(r4,t4)";
$output = preg_split($pattern, $string);
print_r($output);
Current output Array ( [0] => [1] => )
Desired output Array ( [0] => "(y3,x3)," [1] => "(r4,t4)" )
With preg_split() your regex should be matching the delimiters within the string to split the string into an array. Your regex is currently matching the values, and for that, you can use preg_match_all(), like so:
$pattern = "/\(.*?\)/";
$string = "(y3,x3),(r4,t4)";
preg_match_all($pattern, $string, $output);
print_r($output[0]);
This outputs:
Array
(
[0] => (y3,x3)
[1] => (r4,t4)
)
If you want to use preg_split(), you would want to match the , between ),(, but without consuming the parenthesis, like so:
$pattern = "/(?<=\)),(?=\()/";
$string = "(y3,x3),(r4,t4)";
$output = preg_split($pattern, $string);
print_r($output);
This uses a positive lookbehind and positive lookahead to find the , between the two parenthesis groups, and split on them. It also output the same as the above.
You can use a simple regex like \B,\B to split the string and improve the performance by avoiding lookahead or lookbehind regex.
\B is a non-word boundary so it will match only the , between ) and (
Here is a working example:
http://regex101.com/r/cV7bO7/1
$pattern = "/\B,\B/";
$string = "(y3,x3),(r4,t4),(r5,t5)";
$result = preg_split($pattern, $string);
$result will contain:
Array
(
[0] => (y3,x3)
[1] => (r4,t4)
[2] => (r5,t5)
)

Custom regular expression pattern

What's the right pattern to obtain something like that using preg_split.
Input:
Src.[VALUE1] + abs(Src.[VALUE2])
Output:
Array (
[0] => Src.[VALUE1]
[1] => Src.[VALUE2]
)
Instead of using preg_split, using preg_match_all makes more sense in this case:
preg_match_all('/\w+\.\[\w+\]/', $str, $matches);
$matches = $matches[0];
Result of $matches:
Array
(
[0] => Src.[VALUE1]
[1] => Src.[VALUE2]
)
This regex should be fine
Src\.\[[^\]]+\]
But instead of preg_split I'd suggest using preg_match_all
$string = 'Src.[VALUE1] + abs(Src.[VALUE2])';
$matches = array();
preg_match_all('/Src\.\[[^\]]+\]/', $string, $matches);
All matches you're looking for will be bound to $matches[0] array.
I guess preg_match_all is what you want. This works -
$string = "Src.[VALUE1] + abs(Src.[VALUE2])";
$regex = "/Src\.\[.*?\]/";
preg_match_all($regex, $string, $matches);
var_dump($matches[0]);
/*
OUTPUT
*/
array
0 => string 'Src.[VALUE1]' (length=12)
1 => string 'Src.[VALUE2]' (length=12)

Explode with regexp

i have a string like {ASK(Value, Value, 'Sentence', Some_Char)} and i need to get of exploded values in (). What i am doing wrong?
preg_match_all('/\{ASK\((.*?),\)\}/', '{ASK(Value, Value, \'Sentence\', X)}', $matches);
print_r($matches);
Take out the comma from your regular expression, and it matches.
preg_match_all('/\{ASK\((.*?)\)\}/', '{ASK(Value, Value, \'Sentence\', X)}', $matches);
print_r($matches);
//Explode the matched group
$exploded = explode(',',$matches[1]);
print_r($exploded);
/*
* Note that we used $matches[1] instead of $matches[0],
* since the first element contains the entire matched
* expression, and each subsequent element contains the matching groups.
*/
$s = "{ASK(Value, Value, 'Sentence', Some_Char)}";
$p = '#\{ASK\((.*?)\)\}#';
preg_match_all($p, $s, $matches);
print_r($matches);
Simply split & explode
$Myval = "{ASK(Value, Value, 'Sentence', Some_Char)}";
$splitedVal = split('[()]', $Myval);
$explodedVal = explode(",", $splitedVal[1]);
print_r($explodedVal);
// output
Array ( [0] => Value [1] => Value [2] => 'Sentence' [3] => Some_Char )
An easy way to do this (though not entirely contained within the regex) might be:
preg_match_all('/\{ASK\([^)]*\)\}/', '{ASK(Value, Value, \'Sentence\', X)}', $matches);
$values = explode($matches[1]);
So long as your Values, Sentences, and Chars do not contain , or ), then this single regex pattern will deliver without the extra explode() call.
Pattern: ~(?:\G, |ASK\()\K[^,)]+~ (Pattern Demo)
Code: (Demo)
$string="{ASK(Value, Value, 'Sentence', Some_Char)}";
print_r(preg_match_all('~(?:\G, |ASK\()\K[^,)]+~',$string,$out)?$out[0]:[]);
Output:
Array
(
[0] => Value
[1] => Value
[2] => 'Sentence'
[3] => Some_Char
)
The "magic" is in the \G. This tells regex to continue matching at the start of the string or just after the previous match. Here is a similar answer that I've posted: https://stackoverflow.com/a/48373347/2943403

Replacing items in an array using two regular expressions

Can you use two regex in preg_replace to match and replace items in an array?
So for example:
Assume you have:
Array
(
[0] => mailto:9bc0d67a-0#acoregroup.com
[1] => mailto:347c6b#acoregroup.com
[2] => mailto:3b3cce0a-0#acoregroup.com
[3] => mailto:9b690cc#acoregroup.com
[4] => mailto:3b7f59c1-4bc#acoregroup.com
[5] => mailto:cc62c936-7d#acoregroup.com
[6] => mailto:5270f9#acoregroup.com
}
and you have two variables holding regex strings:
$reg = '/mailto:[\w-]+#([\w-]+\.)+[\w-]+/i';
$replace = '/[\w-]+#([\w-]+\.)+[\w-]+/i';
can I:
preg_replace($reg,$replace,$matches);
In order to replace "mailto:9bc0d67a-0#acoregroup.com" with "9bc0d67a-0#acoregroup.com" in each index of the array.
You could try this:
$newArray = preg_replace('/mailto:([\w-]+#([\w-]+\.)+[\w-]+)/i', '$1', $oldArray);
Haven't tested
See here: http://php.net/manual/en/function.preg-replace.php
foreach($array as $ind => $value)
$array[$ind] = preg_replace('/mailto:([\w-]+#([\w-]+\.)+[\w-]+)/i', '$1', $value);
EDIT: gahooa's solution is probably better, because it moves the loop inside preg_replace.
For this type of substitution you should use str_replace it is mutch faster and strongly suggested by the online documentation:
$array = str_replace('mailto:', '', $array);
I think that you are looking for the '$1' submatch groups, as others have already pointed out. But why can't you just do the following:
// strip 'mailto:' from the start of each array entry
$newArray = preg_replace('/^mailto:\s*/i', '', $array);
In fact, seeing as your regex doesn't allow the use of ':' anywhere in the email addresses, you could do it with a simple str_replace():
// remove 'mailto:' from each item
$newArray = str_replace('mailto:', '', $array);

Categories