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_allarray_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=value2string,那么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);