我有这样一个字符串:
key1\value1\key2\value2\key3\value3\key4\value4\key5\value5
我希望它是一个关联数组,这样我就可以:
echo $myArray['key1']; // prints value1
echo $myArray['key3']; // prints value3
//etc...
我知道我可以在反斜杠上 explode ,但不确定如何从那里开始。
最佳答案
使用简单的 regex通过preg_match_all
和 array_combine
通常是最短和最快的选择:
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
都可以。这对于更人性化的用户(也就是非技术用户)来说是有意义的。
限制字母数字键
通常您可能想要禁止除经典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 方案的原始子集。
替代:parse_str()
如果您已经有一个 key=value&key2=value2
字符串,那么 parse_str
奇迹般有效。但是通过将它与 strtr
结合起来甚至可以处理不同的其他分隔符:
# ↓↓ ↑↑
parse_str(strtr($string, ":,", "=&"), $pairs);
它有一些优点和缺点:
- 甚至比两行正则表达式方法更短。
- 预定义了一种众所周知的转义机制,例如用于特殊字符的
%2F
。 - 不允许使用不同的分隔符或内部的未转义分隔符。
- 自动将
keys[]=
转换为数组,您可能需要也可能不需要。
备选方案:explode
+ foreach
你会发现很多 manual key/value string expansion 的例子.尽管这通常是更多代码。由于优化假设,explode
在 PHP 中有些过度使用。然而,由于手动 foreach
和数组集合,分析后通常会变慢。
关于php - 将反斜杠分隔的字符串转换为关联数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5290342/