Find all patterns in a string php - php

This is my string.
$str = '"additional_details":" {"mode_of_transport":"air"}"}],"additional_details":"{"mode_of_transport":"air"}"}],"additional_details":"{"mode_of_transport":"air"}"}],';
I want to find all patterns that start with "{" and end with "}".
I am trying this:
preg_match_all( '/"(\{.*\})"/', $json, $matches );
print_r($matches);
It gives me an output of:
Array
(
[0] => Array
(
[0] => "{"mode_of_transport":"air"}"}],"additional_details":"{"mode_of_transport":"air"}"}],"additional_details":"{"mode_of_transport":"air"}"
)
[1] => Array
(
[0] => {"mode_of_transport":"air"}"}],"additional_details":"{"mode_of_transport":"air"}"}],"additional_details":"{"mode_of_transport":"air"}
)
)
See the array key 1. It gives all matches in one key and other details too.
I want an array of all matches. Like
Array
(
[0] => Array
(
[0] => "{"mode_of_transport":"air"}"}],"additional_details":"{"mode_of_transport":"air"}"}],"additional_details":"{"mode_of_transport":"air"}"
)
[1] => Array
(
[0] => {"mode_of_transport":"air"},
[1] => {"mode_of_transport":"air"},
[2] => {"mode_of_transport":"air"}
)
)
What should I change in my pattern.
Thanks

You can use:
preg_match_all( '/({[^}]*})/', $str, $matches );
print_r($matches[1]);
Array
(
[0] => {"mode_of_transport":"air"}
[1] => {"mode_of_transport":"air"}
[2] => {"mode_of_transport":"air"}
)

Related

How can I convert a string with square brackets into an array?

I got this from the name attribute of a field
name="field[a][2][b][0][c][1][field_name]"
after serializing the form, I got this:
array('field[a][2][b][0][c][1][field_name]'=>'value')
and I need to convert that into the following array:
$field = array (
'a' => array (
[2] => array (
'b' => array (
[0] => array (
'c' => array (
[1] => array (
'field_name'=>'value'
)
)
)
)
)
)
);
do I need some sort of foreach function or php can recognize this string as array?
If you want the result nested, use parse_str().
$text = "field[a][2][b][0][c][1][field_name]=value";
parse_str($text, $result);
print_r($result);
Output:
Array
(
[field] => Array
(
[a] => Array
(
[2] => Array
(
[b] => Array
(
[0] => Array
(
[c] => Array
(
[1] => Array
(
[field_name] => value
)
)
)
)
)
)
)
)
See https://3v4l.org/7nmFT
You can get values in brackets with the regular expression, and then reduce it to the array that you want:
$key = 'field[a][2][b][0][c][1][field_name]';
$value = 'value';
$matches = array();
preg_match_all('/\[([^[]+)\]/', $key, $matches);
$keys = array_reverse($matches[1]);
$result = array_reduce($keys, function ($array, $item) {
return array($item => $array);
}, $value);
Explanation
In the regular expression \[([^[]+)\]:
([^[]+) is matches any symbol except opening bracket, one or more
times, and gets it into the capturing group (I hope you will not have nested brackets);
\[...\] is literally matches brackets around.
The preg_match_all function should populate the $matches array with following data:
Array
(
[0] => Array
(
[0] => [a]
[1] => [2]
[2] => [b]
[3] => [0]
[4] => [c]
[5] => [1]
[6] => [field_name]
)
[1] => Array
(
[0] => a
[1] => 2
[2] => b
[3] => 0
[4] => c
[5] => 1
[6] => field_name
)
)
The $matches[0] have values of a full match and the $matches[1] have values of our first and only capturing group. We have interested only in capturing group values.
Then with the array_reduce function we can simply go through keys in the reverse order, and sequentially wrap our value into an array.
You can use explode function to do it. But the values should have space in between them, for example "Hello World" in which the values would be in Array ( [0] => Hello [1] => world ) but in your case it would be like Array ( [0] => field[a][2][b][0][c][1][field_name] ) until $name as space in-between the characters or word.
$name="field[a][2][b][0][c][1][field_name]"
$name_array = explode(" ",$name);
print_r ($name_array);
When testing your problem on my PHP server with this test code
<form method="post">
<input type="text" name="field[a][2][b][0][c][1][field_name]">
<input type="submit" value="OK">
<form>
<pre>
<?php
if (isset($_POST['field']))
print_r($_POST['field']);
?>
</pre>
I got the following response (after entering the word "hello" into the text box and clicking the "OK" button):
Array ( [a] => Array ( [2] => Array ( [b] =>
Array ( [0] => Array ( [c] => Array ( [1] =>
Array ( [field_name] => hello ) ) ) ) ) ) )
Admittedly, it was formatted nicer, but I am posting from my smartphone, so, please, forgive me for not formatting it again manually.
So, to me it is not quite clear why OP needs extra code to solve his/her problem.
Here is your solution:
https://codebrace.com/editor/b06588218
I have used regex match twice to match variable name and arrays
/[(.+?)]/
matches any values in the array where "?" is lazy matching.
while following regex
/^[^[]+/ matches the variable name.
I have used variable variables to create variable from string extracted from above regex
Result:
Array
(
[a] => Array
(
[2] => Array
(
[b] => Array
(
[0] => Array
(
[c] => Array
(
[1] => Array
(
[field_name] => value
)
)
)
)
)
)
)
I hope this helps

preg_match_all matches array

I have something like this
$matches = array();
preg_match_all('/(`.+`)(\s+AS\s+`.+`)?/i', '`foo` AS `bar`', $matches);
print_r($matches);
The result is
Array
(
[0] => Array
(
[0] => `foo` AS `bar`
)
[1] => Array
(
[0] => `foo` AS `bar`
)
[2] => Array
(
[0] =>
)
)
So, the question is why I don't have ' AS `bar`' in $matches[2][0]?
(If I remove the '?' symbol from regex, I'll get it, but I need the '?' :))
Quantifiers like + are greedy by default so if the first one can match everything it will do so. Making it non-greedy should do the job:
preg_match_all('/(`.+?`)(\s+AS\s+`.+`)?/i', '`foo` AS `bar`', $matches);
And by the way, $matches = array(); is not necessary - the variable is only written to by preg_match_all so it does not need to be initialized/defined before.
php > preg_match_all('/(`.+?`)(\s+AS\s+`.+`)?/i', '`foo` AS `bar`', $matches);
php > print_r($matches);
Array
(
[0] => Array
(
[0] => `foo` AS `bar`
)
[1] => Array
(
[0] => `foo`
)
[2] => Array
(
[0] => AS `bar`
)
)

preg_match_all and umlets

I am using preg_match_all to filter out strings
The string which I have supplied in preg_match_all is
$text = "Friedric'h Wöhler"
after that I use
preg_match_all('/(\"[^"]+\"|[\\p{L}\\p{N}\\*\\-\\.\\?]+)/', $text, $arr, PREG_PATTERN_ORDER);
and the result i get when I print $arr is
Array
(
[0] => Array
(
[0] => friedric
[1] => h
[2] => w
[3] => ouml
[4] => hler
)
[1] => Array
(
[0] => friedric
[1] => h
[2] => w
[3] => ouml
[4] => hler
)
)
Somehow the ö character is replaced by ouml which I am not really sure how to figure this out
I am expecting following result
Array
(
[0] => Array
(
[0] => Friedric'h
[1] => Wöhler
)
)
Per nhahtdh's comment:
$text = "Friedric'h Wöhler";
preg_match_all('/"[^"]+"|[\p{L}\p{N}*.?\\\'-]+/u', $text, $arr, PREG_PATTERN_ORDER);
echo "<pre>";
print_r($arr);
echo "</pre>";
Gives
Array
(
[0] => Array
(
[0] => Friedric'h
[1] => Wöhler
)
)
If you think preg_match_all() is messy, you could take a look at pattern():
$p = '"[^"]+"|[\p{L}\p{N}*.?\\\'-]+'; // automatic delimiters
$text = "Friedric'h Wöhler";
$result = pattern($p)->match($text)->all();

Parsing attributes in PHP using regular expressions

Consider that i have the string,
$string = 'tag2 display="users" limit="5"';
Using the preg_match_all function, i need to get the output
Required o/p
Array
(
[0] => Array
(
[0] => tag2
[1] => tag2
[2] =>
)
[1] => Array
(
[0] => display="users"
[1] => display
[2] => users
)
[2] => Array
(
[0] => limit="5"
[1] => limit
[2] => 5
)
)
I tried using this pattern '/([^=\s]+)="([^"]+)"/' but it is not recognizing the parameter with no value (in this case tag2) Instead it gives the output
What I am getting
Array
(
[0] => Array
(
[0] => display="users"
[1] => display
[2] => users
)
[1] => Array
(
[0] => limit="5"
[1] => limit
[2] => 5
)
)
What will be the pattern for getting the required output ?
EDIT 1: I also need to get the attributes which are not wrapped with quotes ex: attr=val. Sorry for not mentioning before.
Try this:
<?php
$string = 'tag2 display="users" limit="5"';
preg_match_all('/([^=\s]+)(="([^"]+)")?/', $string, $res);
foreach ($res[0] as $r => $v) {
$o[] = array($res[0][$r], $res[1][$r], $res[3][$r]);
}
print_r($o);
?>
It outputs me:
Array
(
[0] => Array
(
[0] => tag2
[1] => tag2
[2] =>
)
[1] => Array
(
[0] => display="users"
[1] => display
[2] => users
)
[2] => Array
(
[0] => limit="5"
[1] => limit
[2] => 5
)
)
I think it's not fully possible to give you with one call what you're looking for, but this is pretty close:
$string = 'tag2 display="users" limit=5';
preg_match_all('/([^=\s]+)(?:="?([^"]+)"?|())?/', $string, $res, PREG_SET_ORDER);
print_r($res);
Output:
Array
(
[0] => Array
(
[0] => tag2
[1] => tag2
[2] =>
[3] =>
)
[1] => Array
(
[0] => display="users"
[1] => display
[2] => users
)
[2] => Array
(
[0] => limit=5
[1] => limit
[2] => 5
)
)
As you can see, the first element has no value, I tried to work around that and offer an empty match now. So this builds the array you were asking for, but has an additional entry on the empty attribute.
However the main point is the PREG_SET_ORDER flag of preg_match_all. Maybe you can live with this output already.
Maybe you're interested in this litte snippet that parses all sorts of attribute styles. <div class="hello" id=foobar style='display:none'> is valid html(5), not pretty, I know…
<?php
$string = '<tag2 display="users" limit="5">';
$attributes = array();
$pattern = "/\s+(?<name>[a-z0-9-]+)=(((?<quotes>['\"])(?<value>.*?)\k<quotes>)|(?<value2>[^'\" ]+))/i";
preg_match_all($pattern, $source, $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
$attributes[$match['name']] = $match['value'] ?: $match['value2'];
}
var_dump($attributes);
will give you
$attributes = array(
'display' => 'users',
'limit' => '5',
);

Multiple matches of the same type in preg_match

I want to use preg_match to return an array of every match for parenthesized subpattern.
I have this code:
$input = '[one][two][three]';
if ( preg_match('/(\[[a-z0-9]+\])+/i', $input, $matches) )
{
print_r($matches);
}
This prints:
Array ( [0] => [one][two][three], [1] => [three] )
... only returning the full string and the last match. I would like it to return:
Array ( [0] => [one][two][three], [1] => [one], [2] => [two], [3] => [three] )
Can this be done with preg_match?
Use preg_match_all() with the + dropped.
$input = '[one][two][three]';
if (preg_match_all('/(\[[a-z0-9]+\])/i', $input, $matches)) {
print_r($matches);
}
Gives:
Array
(
[0] => Array
(
[0] => [one]
[1] => [two]
[2] => [three]
),
[1] => Array
(
[0] => [one]
[1] => [two]
[2] => [three]
)
)
$input = '[one][two][three]';
if ( preg_match_all('/(\[[a-z0-9]+\])+/iU', $input, $matches) )
{
print_r($matches);
}

Categories