多行关联数组 PHP
Multiline to associative array with PHP
我在变量中有一段文本 $s
:
FOO:317263
BAR:abcd
BAZ:s fsiu sfd sdf s dfsdddddd
获得关联数组的最简单方法(并且具有良好的解析性能)是什么:
$a = array('FOO' => '317263', 'BAR' => 'abcd', 'BAZ' => 's fsiu sfd sdf s dfsdddddd');
?
到目前为止,我用过:
preg_match("/^FOO:(.*)$/m", $s, $matches1);
$a['FOO'] = $matches1[1];
preg_match("/^BAR:(.*)$/m", $s, $matches1);
$a['BAR'] = $matches1[1];
...
但是有更简单的方法吗?
若保证':'右边的值不包含':'或"\n":
$s = <<< STRING
FOO:317263
BAR:abcd
BAZ:s fsiu sfd sdf s dfsdddddd
STRING;
$arr = array_column(array_chunk(preg_split("/[:\n]/", $s), 2), 1, 0);
print_r($arr);
这将打印:
Array
(
[FOO] => 317263
[BAR] => abcd
[BAZ] => s fsiu sfd sdf s dfsdddddd
)
你真的可以使用像
这样的非正则表达式方法
$s = 'FOO:317263
BAR:abcd
BAZ:s fsiu sfd sdf s dfsdddddd';
$a = array();
foreach (explode("\n", $s) as $line) {
$chnk = explode(':', $line, 2);
$a[$chnk[0]] = $chnk[1];
}
print_r($a);
用 LF 拆分后,explode(':', $line, 2);
用于拆分第一个冒号出现的行。
如果您可以使用 different/mixed 行结尾,请将 explode("\n", $s)
替换为 preg_split('~\R+~', $s)
甚至 preg_split('~\R+~u', $s)
(如果您处理 Unicode)。
如果你知道你需要做一些比你在问题中透露的更多的匹配,你真的需要一个正则表达式,你可以考虑
$a = array();
if (preg_match_all('~^(\w+)\h*:\h*(.+)~m', $s, $matches)) {
$a = array_combine($matches[1],trim($matches[2]));
}
print_r($a);
见PHP demo and the regex demo。 详情:
^
- 行首(由于 m
标志)
(\w+)
- 第 1 组:一个或多个单词字符
\h*:\h*
- 用零个或多个水平空格包围的冒号
(.+)
- 第 2 组:该行的其余部分。
你也可以使用parse_ini_string
:
$a = parse_ini_string(preg_replace('/^([^:\v]*):(.*)/m', '=\'\'', $s), FALSE);
参见 this PHP demo。
preg_replace('/^([^:\v]*):(.*)/m', '=\'\'', $s)
部分用 =
替换每行中所有第一个 :
个字符,用单引号将第一个 :
之后的部分包裹起来(让 parse_ini_string
正确处理额外的 =
s),并且 parse_ini_string
获取键和值的数组。
从您的字符串构建流并将其读取为 csv:
$s = <<<'DATA'
FOO:317263
BAR:abcd
BAZ:s fsiu sfd sdf s df:sdddddd
DATA;
$handle = fopen("data://text/plain,$s",'r');
$result = [];
while (false !== $cols = fgetcsv($handle, 4096, ':')) {
$result[array_shift($cols)] = implode(':', $cols);
}
print_r($result);
始终使用流,但更“实用”:
$result = array_reduce(file("data://text/plain,$s"), function($c,$i) {
[$k, $v] = explode(':', $i, 2);
$c[$k] = rtrim($v);
return $c;
}, $c=[]);
print_r($result);
我在变量中有一段文本 $s
:
FOO:317263
BAR:abcd
BAZ:s fsiu sfd sdf s dfsdddddd
获得关联数组的最简单方法(并且具有良好的解析性能)是什么:
$a = array('FOO' => '317263', 'BAR' => 'abcd', 'BAZ' => 's fsiu sfd sdf s dfsdddddd');
?
到目前为止,我用过:
preg_match("/^FOO:(.*)$/m", $s, $matches1);
$a['FOO'] = $matches1[1];
preg_match("/^BAR:(.*)$/m", $s, $matches1);
$a['BAR'] = $matches1[1];
...
但是有更简单的方法吗?
若保证':'右边的值不包含':'或"\n":
$s = <<< STRING
FOO:317263
BAR:abcd
BAZ:s fsiu sfd sdf s dfsdddddd
STRING;
$arr = array_column(array_chunk(preg_split("/[:\n]/", $s), 2), 1, 0);
print_r($arr);
这将打印:
Array
(
[FOO] => 317263
[BAR] => abcd
[BAZ] => s fsiu sfd sdf s dfsdddddd
)
你真的可以使用像
这样的非正则表达式方法$s = 'FOO:317263
BAR:abcd
BAZ:s fsiu sfd sdf s dfsdddddd';
$a = array();
foreach (explode("\n", $s) as $line) {
$chnk = explode(':', $line, 2);
$a[$chnk[0]] = $chnk[1];
}
print_r($a);
用 LF 拆分后,explode(':', $line, 2);
用于拆分第一个冒号出现的行。
如果您可以使用 different/mixed 行结尾,请将 explode("\n", $s)
替换为 preg_split('~\R+~', $s)
甚至 preg_split('~\R+~u', $s)
(如果您处理 Unicode)。
如果你知道你需要做一些比你在问题中透露的更多的匹配,你真的需要一个正则表达式,你可以考虑
$a = array();
if (preg_match_all('~^(\w+)\h*:\h*(.+)~m', $s, $matches)) {
$a = array_combine($matches[1],trim($matches[2]));
}
print_r($a);
见PHP demo and the regex demo。 详情:
^
- 行首(由于m
标志)(\w+)
- 第 1 组:一个或多个单词字符\h*:\h*
- 用零个或多个水平空格包围的冒号(.+)
- 第 2 组:该行的其余部分。
你也可以使用parse_ini_string
:
$a = parse_ini_string(preg_replace('/^([^:\v]*):(.*)/m', '=\'\'', $s), FALSE);
参见 this PHP demo。
preg_replace('/^([^:\v]*):(.*)/m', '=\'\'', $s)
部分用 =
替换每行中所有第一个 :
个字符,用单引号将第一个 :
之后的部分包裹起来(让 parse_ini_string
正确处理额外的 =
s),并且 parse_ini_string
获取键和值的数组。
从您的字符串构建流并将其读取为 csv:
$s = <<<'DATA'
FOO:317263
BAR:abcd
BAZ:s fsiu sfd sdf s df:sdddddd
DATA;
$handle = fopen("data://text/plain,$s",'r');
$result = [];
while (false !== $cols = fgetcsv($handle, 4096, ':')) {
$result[array_shift($cols)] = implode(':', $cols);
}
print_r($result);
始终使用流,但更“实用”:
$result = array_reduce(file("data://text/plain,$s"), function($c,$i) {
[$k, $v] = explode(':', $i, 2);
$c[$k] = rtrim($v);
return $c;
}, $c=[]);
print_r($result);