PHP拆分分隔string到键/值对(关联数组)
我有这样的string:
key1\value1\key2\value2\key3\value3\key4\value4\key5\value5
我想它是一个联合数组,所以我可以这样做:
echo $myArray['key1']; // prints value1 echo $myArray['key3']; // prints value3 //etc...
我知道我可以在反斜杠上爆炸,但不知道如何从那里去。
通过preg_match_all
和array_combine
使用简单的正则expression式通常是最短和最快的选项:
preg_match_all("/([^\\\\]+)\\\\([^\\\\]+)/", $string, $p); $array = array_combine($p[1], $p[2]);
这当然是一个特例。 这两个键和值都用\反斜杠分开,所有的键都是对的。 由于必须的双重转义,正则expression式也有点长。
然而,这个scheme可以推广到其他key:value,
string。
不同的key:value,
分隔符
常见的变体包括:和=作为键/值分隔符,或者,和作为对分隔符的其他人。 正则expression式在这种情况下变得相当明显(为了可读性,使用/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+
string模式来使正则expression式跳过不必要的发生:
# ↓ ↓ ↓ preg_match_all("/ (\w+) = ([^,]+) /x", $string, $p);
这是最简单的白名单方法。 如果OTOH要事先声明 /约束整个键/值string,则需要创build一个单独的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);
请注意,这只是一个普通的INIscheme的一个粗糙的子集 。
可选: parse_str()
如果你已经有了一个key=value&key2=value2
string,那么parse_str
就像一个魅力一样。 但通过与strtr
结合,甚至可以处理其他分隔符:
# ↓↓ ↑↑ parse_str(strtr($string, ":,", "=&"), $pairs);
其中有自己的利弊 :
- 甚至比双线正则expression式更短。
- 预先定义了一个众所周知的转义机制,如特殊字符
%2F
)。 - 不允许使用不同的分隔符或非分隔符。
- 自动将
keys[]=
转换为数组,但您可能会也可能不想要。
另类: explode
+ foreach
你会发现许多手动键/值string扩展的例子。 尽pipe这通常是更多的代码。 由于优化假设, explode
在PHP中被过度使用。 通常情况下,由于手动的foreach
和数组收集,分析通常会变慢。
那么这样的事情呢?
$str = 'key1\value1\key2\value2\key3\value3\key4\value4\key5\value5'; $list = explode('\\', $str); $result = array(); for ($i=0 ; $i<count($list) ; $i+=2) { $result[ $list[$i] ] = $list[$i+1]; } var_dump($result);
哪一个会让你:
array 'key1' => string 'value1' (length=6) 'key2' => string 'value2' (length=6) 'key3' => string 'value3' (length=6) 'key4' => string 'value4' (length=6) 'key5' => string 'value5' (length=6)
基本上,这里的想法是:
- 拆分string
- 这将给你一个数组,如
'key1', 'value1', 'key2', 'value2', ...
- 然后,遍历这个列表,跳转2,每次使用:
- 一个元素作为键 –
$i
指向的那个元素 - 就是它之后的那个值 –
$i+1
指向的值
- 一个元素作为键 –
我对RegExp不太好,但是这行代码如何呢?
parse_str(preg_replace("/key(.*?)\\value(.*?)(\\|$)/", "key$1=value$2&", $input_lines), $output);