Greetings, I can't find a regular expression so that preg_match_all would split the string into an array with the name of the parameter and its value. The current option correctly breaks the parameters, but they are broken entirely. What should the correct expression look like?

$row = 'top:223px;left:103px;font-weight: 300; text-transform: uppercase;font-family:Roboto Condensed;font-size:48px;white-space: nowrap;" data-ls="offsetxin:0;delayin:500;offsetxout:0;'; preg_match_all("/([\s\S]*?)*:([\s\S]*?);/", $row, $InnerContent); 
  • What do you want to get something out? explode() n't it easier to do explode() and do without regular expressions? - teran
  • @teran We need an array in the key-value format, and explode() will have to be done 2 times first ; and then on : What is not very beautiful. Regular expression can be managed easier. - Happy_Cougar
  • the main thing is not to get tired of supporting the code later, otherwise the regular is easier than explode first, then it becomes too lazy to name the variables and methods, and so on. - teran
  • @teran I have big doubts that the format of incoming data will change in the future :) - Happy_Cougar
  • one
    @teran Remove the asterisk right before the colon, otherwise it turns out that the first brackets are optional - Mike

2 answers 2

[\s\S] is a whitespace or any character except whitespace. those. any!

Do this:

 preg_match_all("/([^:;]*):([^:;]*)(?:;|$)/", $input_lines, $output_array); 

(?:;|$) is a semicolon or the end of a line.

Online test

  • one
    there *? hence [\s\S] takes exactly to the colon, and the problem is exclusively in the only unnecessary asterisk before this colon - Mike
  • one
    @Mike Yes, this can cause catastrophical backtracking. Although this is not the case, of course. I added another opportunity to take the last value without ; at the end - Crantisz
  • here spaces, probably, will get to keys that is hardly desirable. That is, it will not be text-transform but _text-transform - teran
  • @Crantisz Can you give an input string that would lead to baktreking. on regex101 tests and your expression and (.*?):(.*?); give the same number of steps both on a normal example and on curves - Mike
  • it is better to make an ending in [;|$] , there is no sense in collecting the third group of matches. - teran

It is possible and without a regular season through explode

 $result = array(); foreach(explode(';', $row) as $_params) { list($key, $value) = explode(':', $_params); $result[$key] = $value; } 
  • For better performance, you need to use the 3 parameter function explode otherwise it will be very slow with big data. - And
  • @And what is proposed to write in the third parameter? - teran
  • @teran - by default, this parameter has a PHP_INT_MAX - maximum limit. By the way, it’s still a minus, it’s not advisable to pull the explode at each iteration of the foreach - preferably, the first explode be defined in the variable above the loop, and the second one should be said. that only limit 2 (no more array can be). - And
  • @And I know PHP_INT_MAX . You are talking about big data, but this can only apply to the first explode where the line can actually be long, the second will always have a short line. In foreach explode , obviously, it is called once at the first iteration. That's actually the question arises, IMHO, indicating the last argument as 2, can be useful only when we have a line of 10 megabytes, and the separator character is found only once, and this happens closer to the beginning. Otherwise, I do not understand how specifying the maximum number of elements can help. - teran
  • @teran, it takes time to call a function at each iteration and other consequences in the function, rather than when we defined it immediately in a variable. The last argument will help us to specify the limit and will not immediately allocate memory for the entire size. - And