PHP 5.6/7.0下如何用正则解析多个带引号的键值对?
Hey there! Let's work through this key-value pair parsing headache you're dealing with in PHP 5.6/7.0. I know how frustrating it is to tweak regex after regex without hitting the right fit, so let's break this down into something clean and reusable.
First, let's align on the core requirements: we need to match individual quoted key-value pairs (one at a time, for loop processing) where both keys and values are wrapped in single or double quotes, and handle cases where values might have escaped quotes (like "key"="value with \"escaped\" text").
A Clean, Reusable Regex for Quoted Key-Value Pairs
Here's a regex that handles both single/double quotes, escaped quotes, and flexible spacing around the = sign:
/\G\s*(["'])(.*?)(?<!\\)\1\s*=\s*(["'])(.*?)(?<!\\)\3\s*(?:[,;]|$)/
Let's break down what each part does:
\G: Ensures we start matching right where the last match ended (perfect for looping through pairs one by one)\s*: Matches any leading whitespace (so spacing around pairs doesn't break things)(["']): Captures the opening quote (single or double) for the key(.*?): Non-greedily captures the key content (stops at the next unescaped quote)(?<!\\)\1: Matches the closing quote for the key, ensuring it's not escaped (the(?<!\\)is a negative lookbehind that checks for no backslash before the quote)\s*=\s*: Matches the=sign with optional whitespace on either side- The same pattern repeats for the value: captures the opening quote, value content, and closing unescaped quote
(?:[,;]|$): Matches the separator between pairs (comma/semicolon) or the end of the string (adjust this part if your pairs use a different separator like newlines)
PHP Code Example for Loop Processing
Since you want to process one pair at a time (great for large files), here's how to implement this in PHP 5.6/7.0:
// Example input string (adjust to match your actual data) $input = '"product"="Laptop", \'price\'=\'999.99\', "description"="15\" Screen with 16GB RAM"'; $pattern = '/\G\s*(["\'])(.*?)(?<!\\\)\1\s*=\s*(["\'])(.*?)(?<!\\\)\3\s*(?:[,;]|$)/'; $offset = 0; // Loop through each key-value pair while (preg_match($pattern, $input, $matches, PREG_OFFSET_CAPTURE, $offset)) { // Extract and clean up the key/value (remove escape slashes) $key = stripslashes($matches[2][0]); $value = stripslashes($matches[4][0]); // Do whatever you need with the pair here echo "Processed Pair: Key = '$key', Value = '$value'\n"; // Update the offset to start the next match after the current one $offset = $matches[0][1] + strlen($matches[0][0]); }
Adjustments for Your Specific Scenarios
- Different separators: If your key-value pairs are separated by newlines instead of commas/semicolons, replace
(?:[,;]|$)with(?:\r?\n|$) - No escaped quotes: If you don't need to handle escaped quotes in values, simplify the regex by removing the
(?<!\\)parts (e.g., change(?<!\\)\1to just\1) - Strict spacing: If you don't allow whitespace around the
=sign, remove the\s*around=
This regex is concise, handles common edge cases, and works seamlessly in PHP 5.6 and 7.0 (all PCRE features used are supported in those versions).
内容的提问来源于stack exchange,提问作者Bill in Kansas City

