通过preg_match_all 和array_combine 使用简单的regex 通常是最短和最快的选择:
preg_match_all("/([^\\\\]+)\\\\([^\\\\]+)/", $string, $p);
$array = array_combine($p[1], $p[2]);
现在这当然是一个特例。 keys 和 values 都由 \ 反斜杠分隔,它们都是成对的。由于必要的双重转义,正则表达式也有点长。
不过,这个方案可以推广到其他key:value, 风格的字符串。
不同的key:value, 分隔符
常见的变体包括 : 和 = 作为键/值分隔符,以及 、 或 & 等对分隔符。在这种情况下,正则表达式变得相当明显(带有/x 标志以提高可读性):
# ↓ ↓ ↓
preg_match_all("/ ([^:]+) : ([^,]+) /x", $string, $p);
$array = array_combine($p[1], $p[2]);
这使得将: 和, 交换为其他分隔符变得非常容易。
- 等号
= 而不是 : 冒号。
- 例如
\\t 作为对分隔符(制表符分隔的键:值列表)
- 经典的
& 或; 作为键=值对之间的分隔符。
- 或者只是
\\s 空格或 \\n 换行符。
允许不同的分隔符
您可以通过在键/值/对之间允许不同的分隔符来使其更加灵活/宽容:
# ↓ ↓ ↓
preg_match_all("/ ([^:=]+) [:=]+ ([^,+&]+) /x", $string, $p);
key=value,key2:value2++key3==value3 都可以工作。这对于更人性化的用户(AKA 非技术用户)来说是有意义的。
约束字母数字键
通常您可能想要禁止除经典的key 标识符之外的任何内容。只需使用\w+ 字串模式让正则表达式跳过不需要的事件:
# ↓ ↓ ↓
preg_match_all("/ (\w+) = ([^,]+) /x", $string, $p);
这是最简单的白名单方法。如果 OTOH 你想预先断言/约束整个键/值字符串,然后制作一个单独的preg_match("/^(\w+=[^,]+(,|$))+/", …
去除空格或引号
您可以跳过一些后处理步骤(例如键和值上的trim),只需添加一点点:
preg_match_all("/ \s*([^=]+) \s*=\s* ([^,]+) (?<!\s) /x", $string, $p);
或者例如可选引号:
preg_match_all("/ \s*([^=]+) \s*=\s* '? ([^,]+) (?<![\s']) /x", $string, $p);
INI 样式提取
您可以制作一个基线 INI 文件提取方法:
preg_match_all("/^ \s*(\w+) \s*=\s* ['\"]?(.+?)['\"]? \s* $/xm", $string, $p);
请注意,这只是常见 INI 方案的粗略子集。
如果你已经有一个key=value&key2=value2 字符串,那么parse_str 就像一个魅力。但是通过将它与strtr 结合使用,甚至可以处理不同的其他分隔符:
# ↓↓ ↑↑
parse_str(strtr($string, ":,", "=&"), $pairs);
这有几个自己的优点和缺点:
- 甚至比两行正则表达式方法更短。
- 预定义了众所周知的转义机制,例如
%2F 用于特殊字符)。
- 不允许使用不同的分隔符,或内部未转义的分隔符。
- 自动将
keys[]= 转换为数组,您可能需要也可能不需要。
备选方案:explode + foreach
您会发现很多manual key/value string expansion 的示例。虽然这通常是更多的代码。由于优化假设,explode 在 PHP 中有些过度使用。然而,由于手动 foreach 和数组集合,分析后通常会变慢。