A regular expression to match key-value pairs where the value is in quotation marks or apostrophes

I am trying to complete a PHP application in the next 2 weeks, and I just cannot understand the regex for parsing some attribute strings.

I get random strings that are in a format like this string:

KeyName1="KeyValue1" KeyName2='KeyValue2' 

A single line can contain any number of key value pairs, and values ​​can be separated by single quotes ' or double quotes " in any combination for one string (but they are always limited).

Key values ​​can be any length and contain any character, except that double quotes cannot be inside double quotes, and single quotes cannot be inside single quotes, but double quotes can be inside single quotes, and single quotes can be inside double quotes.

Key parameters can have any number of spaces between them and any number of spaces between the name of the key and the equal sign and equal sign and quotation mark, which launches the key value.

I need to turn a string into an array that looks like this:

 $arrayName["KeyName1"] = "KeyValue1" $arrayName["KeyName2"] = "KeyValue2" 

and etc.

I'm sure this can be done with regular expressions, but all my attempts have failed, and I need help (actually a lot of help :-) to do this, and I hope some of the amazing people here can provide help or at least run me.

+4
source share
4 answers

Of course there are no problems. Let me break it:

 \w+\s*=\s* 

matches an alphanumeric keyword followed by an equal sign (which may be surrounded by a space).

 "[^"]*" 

matches a double double quote, followed by any number of characters except another double quote, then a (closing) double quote.

 '[^']*' 

does the same for single quotes.

Combining this using capture groups ( (...) ) with simple interleaving ( | ), you get

 (\w+)\s*=\s*("[^"]*"|'[^']*') 

In PHP:

 preg_match_all('/(\w+)\s*=\s*("[^"]*"|\'[^\']*\')/', $subject, $result, PREG_SET_ORDER); 

populates $result array of matches. $result[n] will contain details of matching n th, where

  • $result[n][0] - full match
  • $result[n][1] contains the keyword
  • $result[n][2] contains the value (including quotation marks)

Edit:

To map a value element without its quotes, regardless of the type of quotes used, you need a slightly more complex regular expression that uses the positive lookahead statement :

 (\w+)\s*=\s*(["'])((?:(?!\2).)*)\2 

In PHP:

 preg_match_all('/(\w+)\s*=\s*(["\'])((?:(?!\2).)*)\2/', $subject, $result, PREG_SET_ORDER); 

with the results

  • $result[n][0] : full match
  • $result[n][1] : keyword
  • $result[n][2] : quote character
  • $result[n][3] : value

Explanation:

 (["']) # Match a quote (--> group 2) ( # Match and capture --> group 3... (?: # the following regex: (?!\2) # As long as the next character isn't the one in group 2, . # match it (any character) )* # any number of times. ) # End of capturing group 3 \2 # Then match the corresponding quote character. 
+7
source

A small option from Tim Pitsker:

 preg_match_all('/(\w+)\s*=\s*(?|"([^"]*)"|\'([^\']*)\')/', $subject, $result, PREG_SET_ORDER); 

Then you have $result[n][2] , which contains the value without quotes.

+2
source

how

You can use backlinks for what you need, see this template:

 /\b(\w+)\s*=\s*('|\")(.*)\2/U 

\b is the word boundary, ( \w ) captures the key, then = , (captured) apostrophe or quote, followed by something up to \2 , which is the second parenthesis captured (apostrophe or quote). The modifier U means a fuzzy rating .

Example

  // match the key-value pairs $text = "mykey1= \"my'value1'\" mykey2 = 'my\"value2' mykey3=\"my value3\""; preg_match_all("/\b(\w+)\s*=\s*('|\")(.*)\\2/U",$text,$matches); // produce result in format you need $result = array(); for($i=0; $i<count($matches[0]); ++$i) { $result[$matches[1][$i]] = $matches[3][$i]; } 

Result

 Array ( [mykey1] => my'value1' [mykey2] => my"value2 [mykey3] => my value3 ) 
+1
source

Required Conclusion:

 $arrayName["KeyName1"] = "KeyName1" $arrayName["KeyName2"] = "KeyName2" 

I hope you meant:

 $arrayName["KeyName1"] = "KeyValue1" $arrayName["KeyName2"] = "KeyValue2" 

 function paramStringToArray($string) { $array = array_filter(explode(' ', $string)); $result = array(); foreach($array as $value) { $data = explode('=', $value); $data[1] = trim($data[1],'"'); $data[1] = trim($data[1],'\''); $result[$data[0]] = $data[1]; } return $result; } $string = 'KeyName1="KeyValue1" KeyName2=\'KeyValue2\''; echo '<pre>'; var_dump(paramStringToArray($string)); echo '</pre>'; 

Output:

 array(2) { ["KeyName1"]=> "KeyValue1" ["KeyName2"]=> "KeyValue2" } 
0
source

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


All Articles