PHP将分隔字符串分割为键/值对(关联数组)

时间:2021-09-30 22:08:01

I have a string like this:

我有这样一条线:

key1\value1\key2\value2\key3\value3\key4\value4\key5\value5

And I'd like it to be an associative array so that I can do:

我希望它是一个关联数组,这样我就可以:

echo $myArray['key1']; // prints value1
echo $myArray['key3']; // prints value3
//etc...

I know I can explode on the backslash, but not sure how to go from there.

我知道我可以在反斜线上爆炸,但不知道该怎么做。

3 个解决方案

#1


16  

Using a simple regex via preg_match_all and array_combine is often the shortest and quickest option:

通过preg_match_all和array_combine使用一个简单的regex通常是最短和最快的选项:

 preg_match_all("/([^\\\\]+)\\\\([^\\\\]+)/", $string, $p);
 $array = array_combine($p[1], $p[2]);

Now this is of course a special case. Both keys and values are separated by a \ backslash, as are all pairs of them. The regex is also a bit lengthier due to the necessary double escaping.

这当然是一个特例。键和值都由一个\反斜杠分隔,它们的所有对也是如此。由于必要的双重转义,正则表达式也有点长。

However this scheme can be generalized to other key:value,-style strings.

不过,该方案可以推广到其他关键字:值、样式字符串。

Distinct key:value, separators

Common variations include : and = as key/value separators, and , or & and others as pair delimiters. The regex becomes rather obvious in such cases (with the /x flag for readability):

常见的变体包括:和=作为键/值分隔符,以及&和其他作为对分隔符。在这种情况下,regex变得相当明显(使用/x标志表示可读性):

 #                    ↓    ↓    ↓
 preg_match_all("/ ([^:]+) : ([^,]+) /x", $string, $p);
 $array = array_combine($p[1], $p[2]);

Which makes it super easy to exchange : and , for other delimiters.

这使得交换非常容易:对于其他分隔符。

  • Equal signs = instead of : colons.
  • 等号=而不是:冒号。
  • For example \\t as pair delimiter (tab-separated key:value lists)
  • 例如\t作为一对分隔符(表分隔键:值列表)
  • Classic & or ; as separator between key=value pairs.
  • 经典&或;作为键=值对之间的分隔符。
  • Or just \\s spaces or \\n newlines even.
  • 或者只是\s空间或\n新线。

Allow varying delimiters

You can make it more flexible/forgiving by allowing different delimiters between keys/values/pairs:

通过允许键/值/对之间有不同的分隔符,您可以使它更灵活/宽容:

 #                    ↓      ↓       ↓
 preg_match_all("/ ([^:=]+) [:=]+ ([^,+&]+) /x", $string, $p);

Where both key=value,key2:value2++key3==value3 would work. Which can make sense for more human-friendlinies (AKA non-technical users).

当两个键都=value时,key2:value2+ key3= value3将有效。这对于更多的人类朋友(也就是非技术用户)来说是有意义的。

Constrain alphanumeric keys

Oftentimes you may want to prohibit anything but classic key identifiers. Just use a \w+ word string pattern to make the regex skip over unwanted occurences:

通常,您可能想要禁止除经典键标识符之外的任何内容。只需使用一个\w+字串模式,使regex跳过不希望出现的情况:

 #                   ↓   ↓    ↓
 preg_match_all("/ (\w+) = ([^,]+) /x", $string, $p);

This is the most trivial whitelisting approach. If OTOH you want to assert/constrain the whole key/value string beforehand, then craft a separate preg_match("/^(\w+=[^,]+(,|$))+/", …

这是最普通的白名单方法。如果OTOH你想维护/预先制约整个键/值字符串,然后制定单独的preg_match(" / ^(\ w + =(^,)+ | $())+ /”,…

Strip spaces or quoting

You can skip a few post-processing steps (such as trim on keys and values) with a small addition:

您可以跳过一些后处理步骤(如在键和值上进行修剪),添加一点:

 preg_match_all("/ \s*([^=]+) \s*=\s* ([^,]+) (?<!\s) /x", $string, $p);

Or for instance optional quotes:

或例如可选引号:

 preg_match_all("/ \s*([^=]+) \s*=\s* '? ([^,]+) (?<![\s']) /x", $string, $p);

INI-style extraction

And you can craft a baseline INI-file extraction method:

您还可以设计一个基线小文件提取方法:

 preg_match_all("/^ \s*(\w+) \s*=\s* ['\"]?(.+?)['\"]? \s* $/xm", $string, $p);

Please note that this is just a crude subset of common INI schemes.

请注意,这只是普通INI方案的一个粗略的子集。

Alternative: parse_str()

If you have a key=value&key2=value2 string already, then parse_str works like a charm. But by combining it with strtr can even process varying other delimiters:

如果您已经有一个键=value&key2=value2字符串,那么parse_str就像一个魔咒一样工作。但通过与strtr的结合,甚至可以处理不同的其他分隔符:

 #                         ↓↓    ↑↑
 parse_str(strtr($string, ":,", "=&"), $pairs);

Which has a couple of pros and cons of its own:

它有自己的优缺点:

  • Even shorter than the two-line regex approach.
  • 甚至比两行regex方法还要短。
  • Predefines a well-known escaping mechanism, such as %2F for special characters).
  • 预先定义一个众所周知的转义机制,例如用于特殊字符的%2F)。
  • Does not permit varying delimiters, or unescaped delimiters within.
  • 不允许在内部使用不同的分隔符或未转义的分隔符。
  • Automatically converts keys[]= to arrays, which you may or may not want though.
  • 自动将键[]=转换为数组,您可能想要,也可能不想要。

Alternative: explode + foreach

You'll find many examples of manual key/value string expansion. Though this is often more code. explode is somewhat overused in PHP due to optimization assumptions. After profiling often turns out to be slower however due to the manual foreach and array collection.

您会发现许多手动键/值字符串扩展的例子。虽然这通常是更多的代码。由于优化假设的原因,在PHP中使用了blow。然而,在分析之后,通常会由于每个和数组的收集而变得更慢。

#2


6  

What about something like this :

像这样的东西怎么样:

$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);

Which would get you :

这会让你:

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)


Basically, here, the idea is to :

基本上,这里的想法是:

  • split the string
  • 分割字符串
  • which will give you an array such as 'key1', 'value1', 'key2', 'value2', ...
  • 它会给你一个数组,比如'key1', 'value1', 'key2', 'value2',…
  • and, then, iterate over this list, with a jump of 2, using each time :
    • one element as the key -- the one pointed by $i
    • 一个元素作为键——一个由$i指向的元素
    • the one just after it as the value -- the one pointed by $i+1
    • 在它后面的那个作为值,那个用$i+1表示的
  • 然后,在这个列表上进行迭代,每次跳转2,使用:一个元素作为键——一个元素指向$i,另一个在它后面作为值——一个元素指向$i+1

#3


0  

I am not that good with RegExp but how about this one line code

我不太擅长RegExp,但是这一行代码怎么样

parse_str(preg_replace("/key(.*?)\\value(.*?)(\\|$)/", "key$1=value$2&", $input_lines), $output);

#1


16  

Using a simple regex via preg_match_all and array_combine is often the shortest and quickest option:

通过preg_match_all和array_combine使用一个简单的regex通常是最短和最快的选项:

 preg_match_all("/([^\\\\]+)\\\\([^\\\\]+)/", $string, $p);
 $array = array_combine($p[1], $p[2]);

Now this is of course a special case. Both keys and values are separated by a \ backslash, as are all pairs of them. The regex is also a bit lengthier due to the necessary double escaping.

这当然是一个特例。键和值都由一个\反斜杠分隔,它们的所有对也是如此。由于必要的双重转义,正则表达式也有点长。

However this scheme can be generalized to other key:value,-style strings.

不过,该方案可以推广到其他关键字:值、样式字符串。

Distinct key:value, separators

Common variations include : and = as key/value separators, and , or & and others as pair delimiters. The regex becomes rather obvious in such cases (with the /x flag for readability):

常见的变体包括:和=作为键/值分隔符,以及&和其他作为对分隔符。在这种情况下,regex变得相当明显(使用/x标志表示可读性):

 #                    ↓    ↓    ↓
 preg_match_all("/ ([^:]+) : ([^,]+) /x", $string, $p);
 $array = array_combine($p[1], $p[2]);

Which makes it super easy to exchange : and , for other delimiters.

这使得交换非常容易:对于其他分隔符。

  • Equal signs = instead of : colons.
  • 等号=而不是:冒号。
  • For example \\t as pair delimiter (tab-separated key:value lists)
  • 例如\t作为一对分隔符(表分隔键:值列表)
  • Classic & or ; as separator between key=value pairs.
  • 经典&或;作为键=值对之间的分隔符。
  • Or just \\s spaces or \\n newlines even.
  • 或者只是\s空间或\n新线。

Allow varying delimiters

You can make it more flexible/forgiving by allowing different delimiters between keys/values/pairs:

通过允许键/值/对之间有不同的分隔符,您可以使它更灵活/宽容:

 #                    ↓      ↓       ↓
 preg_match_all("/ ([^:=]+) [:=]+ ([^,+&]+) /x", $string, $p);

Where both key=value,key2:value2++key3==value3 would work. Which can make sense for more human-friendlinies (AKA non-technical users).

当两个键都=value时,key2:value2+ key3= value3将有效。这对于更多的人类朋友(也就是非技术用户)来说是有意义的。

Constrain alphanumeric keys

Oftentimes you may want to prohibit anything but classic key identifiers. Just use a \w+ word string pattern to make the regex skip over unwanted occurences:

通常,您可能想要禁止除经典键标识符之外的任何内容。只需使用一个\w+字串模式,使regex跳过不希望出现的情况:

 #                   ↓   ↓    ↓
 preg_match_all("/ (\w+) = ([^,]+) /x", $string, $p);

This is the most trivial whitelisting approach. If OTOH you want to assert/constrain the whole key/value string beforehand, then craft a separate preg_match("/^(\w+=[^,]+(,|$))+/", …

这是最普通的白名单方法。如果OTOH你想维护/预先制约整个键/值字符串,然后制定单独的preg_match(" / ^(\ w + =(^,)+ | $())+ /”,…

Strip spaces or quoting

You can skip a few post-processing steps (such as trim on keys and values) with a small addition:

您可以跳过一些后处理步骤(如在键和值上进行修剪),添加一点:

 preg_match_all("/ \s*([^=]+) \s*=\s* ([^,]+) (?<!\s) /x", $string, $p);

Or for instance optional quotes:

或例如可选引号:

 preg_match_all("/ \s*([^=]+) \s*=\s* '? ([^,]+) (?<![\s']) /x", $string, $p);

INI-style extraction

And you can craft a baseline INI-file extraction method:

您还可以设计一个基线小文件提取方法:

 preg_match_all("/^ \s*(\w+) \s*=\s* ['\"]?(.+?)['\"]? \s* $/xm", $string, $p);

Please note that this is just a crude subset of common INI schemes.

请注意,这只是普通INI方案的一个粗略的子集。

Alternative: parse_str()

If you have a key=value&key2=value2 string already, then parse_str works like a charm. But by combining it with strtr can even process varying other delimiters:

如果您已经有一个键=value&key2=value2字符串,那么parse_str就像一个魔咒一样工作。但通过与strtr的结合,甚至可以处理不同的其他分隔符:

 #                         ↓↓    ↑↑
 parse_str(strtr($string, ":,", "=&"), $pairs);

Which has a couple of pros and cons of its own:

它有自己的优缺点:

  • Even shorter than the two-line regex approach.
  • 甚至比两行regex方法还要短。
  • Predefines a well-known escaping mechanism, such as %2F for special characters).
  • 预先定义一个众所周知的转义机制,例如用于特殊字符的%2F)。
  • Does not permit varying delimiters, or unescaped delimiters within.
  • 不允许在内部使用不同的分隔符或未转义的分隔符。
  • Automatically converts keys[]= to arrays, which you may or may not want though.
  • 自动将键[]=转换为数组,您可能想要,也可能不想要。

Alternative: explode + foreach

You'll find many examples of manual key/value string expansion. Though this is often more code. explode is somewhat overused in PHP due to optimization assumptions. After profiling often turns out to be slower however due to the manual foreach and array collection.

您会发现许多手动键/值字符串扩展的例子。虽然这通常是更多的代码。由于优化假设的原因,在PHP中使用了blow。然而,在分析之后,通常会由于每个和数组的收集而变得更慢。

#2


6  

What about something like this :

像这样的东西怎么样:

$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);

Which would get you :

这会让你:

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)


Basically, here, the idea is to :

基本上,这里的想法是:

  • split the string
  • 分割字符串
  • which will give you an array such as 'key1', 'value1', 'key2', 'value2', ...
  • 它会给你一个数组,比如'key1', 'value1', 'key2', 'value2',…
  • and, then, iterate over this list, with a jump of 2, using each time :
    • one element as the key -- the one pointed by $i
    • 一个元素作为键——一个由$i指向的元素
    • the one just after it as the value -- the one pointed by $i+1
    • 在它后面的那个作为值,那个用$i+1表示的
  • 然后,在这个列表上进行迭代,每次跳转2,使用:一个元素作为键——一个元素指向$i,另一个在它后面作为值——一个元素指向$i+1

#3


0  

I am not that good with RegExp but how about this one line code

我不太擅长RegExp,但是这一行代码怎么样

parse_str(preg_replace("/key(.*?)\\value(.*?)(\\|$)/", "key$1=value$2&", $input_lines), $output);