How to split a string into a 2D array using Regex?

I have a problem that seems simple at first, but defeated my meager regex skills. I have a string that I need to convert to an array, and then process the values ​​accordingly, which is quite simple, but the format of the string cannot be changed (it is created elsewhere), and the logic of this confused me.

Line:

[6] [2] [3] 12.00; [5] [4] 

Basically this is a set of identifiers and decimal values ​​(in this case id 3 == 12.00). The number of identifiers can change at any time, and decimal values ​​can be in any or all identifiers.

In an ideal world, I will have the following array:

 Array ( [0] => Array ( [id] => 6 [num] => ) [1] => Array ( [id] => 2 [num] => ) [2] => Array ( [id] => 3 [num] => 12.00 ) Etc... 

Do any of the regular expression masters help you, how can this be done with fewer curses than I could have achieved?

I have so far been able to extract the identifier using:

 preg_match_all('@\[(.*?)\]@s', $string, $array); 

and decimal places using:

 preg_match_all('/([0-9]+[,\.]{1}[0-9]{2})/', $string, $array); 

but lose the correlation between id and values.

+6
source share
5 answers

Example:

 <?php $string = '[6] [2] [3] 12.00; [5] [4]'; preg_match_all('/\[(?P<id>\d+)\](?: (?P<num>[\d\.]+);)?/', $string, $matches, PREG_SET_ORDER); var_dump($matches); 

Conclusion:

 array(5) { [0]=> array(3) { [0]=> string(3) "[6]" ["id"]=> string(1) "6" [1]=> string(1) "6" } [1]=> array(3) { [0]=> string(3) "[2]" ["id"]=> string(1) "2" [1]=> string(1) "2" } [2]=> array(5) { [0]=> string(10) "[3] 12.00;" ["id"]=> string(1) "3" [1]=> string(1) "3" ["num"]=> string(5) "12.00" [2]=> string(5) "12.00" } [3]=> array(3) { [0]=> string(3) "[5]" ["id"]=> string(1) "5" [1]=> string(1) "5" } [4]=> array(3) { [0]=> string(3) "[4]" ["id"]=> string(1) "4" [1]=> string(1) "4" } } 
+3
source

If you are happy with the list of identifiers or NUM, then you can simply combine the two working regular expressions into one call:

 preg_match_all('@ \[(?P<id> \d+ )] | (?P<num> [\d,.]+) @xs', $string, $array, PREG_SET_ORDER); 

This will give you a list of associative arrays with the id or num setting if you also use the PREG_SET_ORDER flag.

+1
source

Something like that? My php skills are pretty weak, so you will need to check how to access the named id/num capture groups.

 preg_match_all('/\[(?P<id>\d+)\]\s*(?P<num>[-+]?\b[0-9]+(?:\.[0-9]+)?\b)?/', $subject, $result, PREG_SET_ORDER); for ($matchi = 0; $matchi < count($result); $matchi++) { for ($backrefi = 0; $backrefi < count($result[$matchi]); $backrefi++) { # Matched text = $result[$matchi][$backrefi]; } } 

How it works:

 " \[ # Match the character "[" literally (?<id> # Match the regular expression below and capture its match into backreference with name "id" \d # Match a single digit 0..9 + # Between one and unlimited times, as many times as possible, giving back as needed (greedy) ) ] # Match the character "]" literally \s # Match a single character that is a "whitespace character" (spaces, tabs, line breaks, etc.) * # Between zero and unlimited times, as many times as possible, giving back as needed (greedy) (?<num> # Match the regular expression below and capture its match into backreference with name "num" [-+] # Match a single character present in the list "-+" ? # Between zero and one times, as many times as possible, giving back as needed (greedy) \b # Assert position at a word boundary [0-9] # Match a single character in the range between "0" and "9" + # Between one and unlimited times, as many times as possible, giving back as needed (greedy) (?: # Match the regular expression below \. # Match the character "." literally [0-9] # Match a single character in the range between "0" and "9" + # Between one and unlimited times, as many times as possible, giving back as needed (greedy) )? # Between zero and one times, as many times as possible, giving back as needed (greedy) \b # Assert position at a word boundary )? # Between zero and one times, as many times as possible, giving back as needed (greedy) " 

He also cares about negative values.

+1
source

Take a look at the php explode command - http://php.net/manual/en/function.explode.php

0
source

This is not a regex approach, but maybe it works for you: (of course, it can be improved)

 $str = "[6] [2] [3] 12.00; [5] [4]"; $str = str_replace(array('[',']'), '', $str); $arr = explode(' ', $str); $array = array(); for($i=0 ; $i < count($arr) ; $i++) { $isValue = strpos($arr[$i], '.'); if($isValue !== false){ continue; } $key = $arr[$i]; $ret = array( 'id' => $key , 'num' => ''); $nextIsFloat = strstr($arr[$i+1], ';', TRUE); if(!$nextIsFloat){ $array[] = $ret; continue; }else{ $ret['num'] = $nextIsFloat; $array[] = $ret; $i++; } } 
0
source

Source: https://habr.com/ru/post/901538/


All Articles