this is my string:
zzzzzzz-------eh="koko"------eh="zizi"--------eh="mimi"--------xxxxxx
i need a reg-expression to extract koko, zizi and mimi
but eh='zizi' is optional:
so if it doesn't exist like in :
zzzzzzz----------eh="koko"-----------------eh="mimi"----------xxxxxx
i should get only koko and mimi.
the '---' are some text.
i tried
preg_match_all('#zzzzzzz(.*eh="([^"]*)"){2,3}.*xxxxxx#Uix', $strg , $out, PREG_SET_ORDER);
but it doesn't work.
note: the whole thing is like :
zzzzzzz--...--xxxxxxzzzzzzz--...--xxxxxxzzzzzzz--...--xxxxxxzz...
i need them grouped
like :
array():{
[0]:array():{
[0]:"zizi",
[1]:"mimi",
[2]:"koko",
},
[1]:array():{
[0]:"zizi",
[1]:"koko",
},
[2]:array():{
[0]:"zizi",
[1]:"fofo",
[2]:"bingo",
},
}
Why not just:
preg_match_all('/(?<=eh=")([^"]+)(?=")/', $strg, $out, PREG_SET_ORDER);
Regex101 Demo
This can be solved by capturing all strings preceded by =" until a " is found:
$s='zzzzzzz-------eh="koko"------eh="zizi"--------eh="mimi"--------xxxxxx';
if (preg_match_all('~(?<==")[^"]*~', $s, $arr))
print_r($arr);
OUTPUT:
Array
(
[0] => Array
(
[0] => koko
[1] => zizi
[2] => mimi
)
)
How about:
$str = 'zzzzzzz-------eh="koko"------eh="zizi"--------eh="mimi"--------xxxxxxzzzzzzz----------eh="koko"-----------------eh="mimi"----------xxxxxx';
$arr = preg_split('/(?<=x)(?=z)/', $str);
foreach($arr as $s) {
preg_match_all('/"([^"]+)"/', $s, $out);
$arr_out[] = $out[1];
}
print_r($arr_out);
output:
Array
(
[0] => Array
(
[0] => koko
[1] => zizi
[2] => mimi
)
[1] => Array
(
[0] => koko
[1] => mimi
)
)
Related
Hello :) I am a beginner in PHP.
I tried several times but did not succeed
I would like to parse a String like :
[1,[01,11,12],[20,21,22]]
to
`
arr[0][0]=>1
arr[1][0]=>01
arr[1][1]=>11
arr[1][2]=>12
arr[2][0]=>20
arr[2][1]=>21
arr[2][2]=>22
`
You can split your string on a comma that is not enclosed by [ and ] using this regex (inspired by this answer) with preg_split:
,(?![^\[]*\])
and then trim surrounding [ and ] from the resultant parts and split those strings on commas into succeeding elements of the output array. For example:
$string = '[1,[01,11,12] ,4 ,5, [20,21,22]]';
$parts = preg_split('/,(?![^\[]*\])/', $string, -1, PREG_SPLIT_DELIM_CAPTURE);
$output = array();
foreach ($parts as $part) {
$part = trim($part, '[] ');
$output[] = explode(',', $part);
}
print_r($output);
Output:
Array
(
[0] => Array
(
[0] => 1
)
[1] => Array
(
[0] => 01
[1] => 11
[2] => 12
)
[2] => Array
(
[0] => 4
)
[3] => Array
(
[0] => 5
)
[4] => Array
(
[0] => 20
[1] => 21
[2] => 22
)
)
Demo on 3v4l.org
If you're 100% certain of the source and safety of the string, you can also just use eval:
eval("\$output = $string;");
The result will be the same.
I have music chord and lyrics like this :
<p>[Fm] [Gm] [Dm]</p>
<p>لورم ایپسوم ، لورم ایپسوم</p>
<p>[A] [Asus4] [Bb]</p>
<p>لورم ایپسوم ، لورم ایپسوم</p>
the "p" tags generated by wordpress editor for each line.
I collect the Chord with brackets by using :
preg_match_all("/\[[^\]]*\]/", $content , $matches);
And result is :
[0] => [Fm]
[1] => [Gm]
[2] => [Dm]
[3] => [A]
[4] => [Asus4]
[5] => [Bb]
but I need to collect the chords from right to left and my array should be like this one :
[0] => [Dm]
[1] => [Gm]
[2] => [Fm]
[3] => [Bb]
[4] => [Asus4]
[5] => [A]
Thanks.
You could try to capture a single line first by matching to: (\[[^\]]*\])+(\<\\p\>){1}
You can then take a matched string and match it against your expression: /\[[^\]]*\]/.
If you take these secondary matches and put them in a 2d array you'll now have a object with this structure:
[0] => [Fm, Gm, Dm]
[1] => [A, Asus4, Bd]
Some (pseudo)code:
$outputarr = [];
preg_match_all("/(\[[^\]]*\])+(\<\\p\>){1}/", $content , $matches);
foreach ($matches as &$value) {
$internalarray = [];
preg_match_all("//\[[^\]]*\]/", $value , $matches2);
foreach ($matches2 as &$value2) {
array_push($internalarray, $value2);
}
array_push($outputarr, $internalarray);
}
You can now call the array_reverse function on elements [0] and [1] to get:
[0] => [Dm, Gm, Fm]
[1] => [Bd, Asus4, A]
And you can finally go from that to a single array by doing this:
$arr = [];
foreach ($outputarr as &$value) {
$arr = array_merge($arr, $value);
}
This should give your wanted inside variable $arr:
[0] => [Dm]
[1] => [Gm]
[2] => [Fm]
[3] => [Bb]
[4] => [Asus4]
[5] => [A]
ps: I haven't taken the whitespace characters into account and ((\[[^\]]*\])|\s)+(\<\\p\>){1} could be the better one. Furthermore this code could be improved by using array_merge and as such bypassing manual array_push
$content = "<p>[Fm] [Gm] [Dm]</p>
<p>لورم ایپسوم ، لورم ایپسوم</p>
<p>[A] [Asus4] [Bb]</p>
<p>لورم ایپسوم ، لورم ایپسوم</p>";
preg_match_all("/<p>.*<\/p>/", $content , $nodes);
$final = [];
foreach ($nodes[0] as $node ) {
if(!empty($node)) {
preg_match_all("/\[[^\]]*\]/", $node , $matches);
if(!empty($matches[0])) {
$final = array_merge($final, array_reverse($matches[0]));
}
}
}
print_r($final);
I have the following regexp that works great.
$str = "ID: {{item:id}} & First name: {{item:first_name}} & Page Title: {{page:title}}";
preg_match_all('/(?<={{)[^}]*(?=}})/', $str, $matches);
print_r($matches);
Returns:
Array
(
[0] => Array
(
[0] => item:id
[1] => item:first_name
[2] => page:title
)
)
How do I need to modify the regex to force it to match the item:id and item:first_name only (or any other string starting with "item:")? I tried adding the "item" to the regex (in several different places) but it didn't work.
You can use:
preg_match_all('/(?<={{)item:[^}]*(?=}})/', $str, $matches);
print_r($matches[0]);
Array
(
[0] => item:id
[1] => item:first_name
)
With this you can group the tokens, so you don't need to limit the expression to any single type:
(?<={{)(.+?)(?:\:)(.+?)(?=}})
Example of utilization:
$str = "ID: {{item:id}} & First name: {{item:first_name}} & Page Title: {{page:title}}";
preg_match_all('/(?<={{)(.+?)(?:\:)(.+?)(?=}})/', $str, $matches);
$tokens = array();
foreach ($matches[0] as $i => $v) {
$tokens[$matches[1][$i]][] = $matches[2][$i];
}
echo '<pre>';
print_r($tokens);
Output:
Array
(
[item] => Array
(
[0] => id
[1] => first_name
)
[page] => Array
(
[0] => title
)
)
I want to extract values from a string to call an array for basic template functionality:
$string = '... #these.are.words-I_want.to.extract# ...';
$output = preg_replace_callback('~\#([\w-]+)(\.([\w-]+))*\#~', function($matches) {
print_r($matches);
// Replace matches with array value: $these['are']['words-I_want']['to']['extract']
}, $string);
This gives me:
Array
(
[0] => #these.are.words-I_want.to.extract#
[1] => these
[2] => .extract
[3] => extract
)
But I'd like:
Array
(
[0] => #these.are.words-I_want.to.extract#
[1] => these
[2] => are
[3] => words-I_want
[4] => to
[5] => extract
)
Which changes do I need to make to my regex?
It seems that the words are simply dot separated, so match sequences of what you don't want:
preg_replace_callback('/[^#.]+/', function($match) {
// ...
}, $str);
Should give the expected results.
However, if the # characters are the boundary of where the matching should take place, you would need a separate match and then use a simple explode() inside:
preg_replace_callback('/#(.*?)#/', function($match) {
$parts = explode('.', $match[1]);
// ...
}, $str);
You can use array_merge() function to merge the two resulting arrays:
$string = '... #these.are.words-I_want.to.extract# ...';
$result = array();
if (preg_match('~#([^#]+)#~', $string, $m)) {
$result[] = $m[0];
$result = array_merge($result, explode('.', $m[1]));
}
print_r($result);
Output:
Array
(
[0] => #these.are.words-I_want.to.extract#
[1] => these
[2] => are
[3] => words-I_want
[4] => to
[5] => extract
)
I have an array which looks like this:
Array
(
[0] => Array
(
[0] => TE=140414100000 cd =AB1234 ggg =1234567 gbh =2
[7] => nd: DA1AAAAAAAAAA: TD = 140414:
)
[1] => Array
(
[0] => TE=140414100000 cd =AB1234 ggg =1234567 ghb =2
[7] => nd: DA1AAAAAAAAAA: TD = 140414:
)
)
what I am trying to acomplish is to parse data within each sub array and create a new multidimensional array with the parsed data.
Example: the data in parentheses below is what should be returned in new multidimensional array
Array
(
[0] => Array
(
[0] => te=(140414100000) cd =AB(1234) ggg =1234567 ghb =2
[7] => nd: DA(1)(AAAAAAAAAA): TD = (140414):
)
[1] => Array
(
[0] => te=(140414100000) cd =AB(1234) ggg =1234567 ghb =2
[7] => nd: DA(2)(BBBBBBBBBB): TD = (140414):
)
)
What I want to return:
Array
(
[0] => Array
(
[0] => 140414100000
[1] => 1234
[2] => 1
[3] => AAAAAAAAAA
[4] => 140414
)
[1] => Array
(
[0] => 140414100000
[1] => 1234
[2] => 2
[3] => BBBBBBBBBB
[4] => 140414
)
).
So my question is what would be the best way to acomplish this?
This is what I have come up with. It works, however is seems very inefficient as it adds a lot of empty arrays which have to be cleaned up.
foreach($new as $key => $val){
foreach($val as $res){
preg_match_all('%te=([0-9]{12})\s%',$res,$matches);
$out[$key][] = $matches[1][0];
preg_match_all('%cd\s+=AB([0-9]{4})%',$res,$matches);
$out[$key][] = $matches[1][0];
preg_match_all('%nd:\sDA([0-9]{1})%',$res,$matches);
$out[$key]['node'] = $matches[1][0];
preg_match_all('%nd:\sDA[0-9]{1}([a-zA-Z]{10,14}):%',$res,$matches);
$out[$key]['rset'] = $matches[1][0];
preg_match_all('%td\s=\s([0-9]{6}):%',$res,$matches);
$out[$key]['trdt'] = $matches[1][0];
}
}
foreach($out as $v){
$v = array_values(array_filter($v));
$return[] = $v;
}
return $return;
Thanks in advance.
UPDATED:
This worked and is much more efficient. Thanks for the example Shankar
foreach($new as $key => $val){
$v = implode('', $val);
preg_match_all("%te=([0-9]{12})|cd\s+=AB([0-9]{4})|nd:\sDA([0-9]{1})|([A-Z]{3,7}):|td=\s([0-9]{6}):%",$v,$matches);
$new_array[$key]['time'] = $matches[1][0];
$new_array[$key]['code'] = $matches[2][1];
$new_array[$key]['sp'] = $matches[3][2];
$new_array[$key]['rset'] = $matches[4][3];
$new_array[$key]['trfdt'] = $matches[5][4];
}
echo "<pre>";
print_r($new_array);
echo "</pre>";
Loop through your array and implode each array element and use a preg_match_all() to capture all the entries bewteen ( and ) and then pass those matches to your new array.
foreach($arr as $k=>$arr1)
{
$v = implode('',$arr1);
preg_match_all('^\((.*?)\)^', $v, $matches);
$new_arr[]=$matches[1];
}
print_r($new_arr);
Working Demo