如何从用 print_r 打印的数组的输出创建一个数组?
Posted
技术标签:
【中文标题】如何从用 print_r 打印的数组的输出创建一个数组?【英文标题】:How create an array from the output of an array printed with print_r? 【发布时间】:2011-10-24 22:49:04 【问题描述】:我有一个数组:
$a = array('foo' => 'fooMe');
我愿意:
print_r($a);
哪个打印:
Array ( [foo] => printme )
有没有功能,所以在做的时候:
needed_function(' Array ( [foo] => printme )');
我会找回数组array('foo' => 'fooMe');
吗?
【问题讨论】:
只是为了添加更多关于“为什么?”的上下文,我遇到了同样的问题。以前的开发人员留下了从另一个平台解析数据并将结果记录为 print_r 字符串的代码(因为它对人类阅读很友好)。一段时间后,重新解析这些信息的需求出现了,唯一的记录就是日志。 你可以看这里:blog.nixarsoft.com/2021/04/16/convert-print_r-result-to-json @kodmanyagha 该页面不处理子数组(在遇到Array(
时需要递归调用),也不处理特殊情况。无论如何,print_r() 的结果是不确定的,因为键/值可以包含 print_r 或 \n
使用的分隔符,并且没有任何内容被转义...
【参考方案1】:
我实际上编写了一个函数,将“字符串数组”解析为实际数组。显然,它有点 hacky 之类的,但它适用于我的测试用例。这是http://codepad.org/idlXdij3 的功能原型的链接。
我也将内联代码发布给那些不想点击链接的人:
<?php
/**
* @author ninetwozero
*/
?>
<?php
//The array we begin with
$start_array = array('foo' => 'bar', 'bar' => 'foo', 'foobar' => 'barfoo');
//Convert the array to a string
$array_string = print_r($start_array, true);
//Get the new array
$end_array = text_to_array($array_string);
//Output the array!
print_r($end_array);
function text_to_array($str)
//Initialize arrays
$keys = array();
$values = array();
$output = array();
//Is it an array?
if( substr($str, 0, 5) == 'Array' )
//Let's parse it (hopefully it won't ***)
$array_contents = substr($str, 7, -2);
$array_contents = str_replace(array('[', ']', '=>'), array('#!#', '#?#', ''), $array_contents);
$array_fields = explode("#!#", $array_contents);
//For each array-field, we need to explode on the delimiters I've set and make it look funny.
for($i = 0; $i < count($array_fields); $i++ )
//First run is glitched, so let's pass on that one.
if( $i != 0 )
$bits = explode('#?#', $array_fields[$i]);
if( $bits[0] != '' ) $output[$bits[0]] = $bits[1];
//Return the output.
return $output;
else
//Duh, not an array.
echo 'The given parameter is not an array.';
return null;
?>
【讨论】:
不能很好地工作 - 它会删除键和值中的空格! codepad.org/GYL4M2xi @Elias 我更新了上面的脚本,不太记得我为什么要替换空格。这是一个修订版本的链接(基于您的代码):codepad.org/od79B28T 对于简单的数组,这是可行的,但是对于多维数组,它会失败。只需使用this。 我在 $bits[1] 中添加了一个 trim(),因为它在值周围添加了很多空白空间。【参考方案2】:如果要将数组存储为字符串,请使用serialize
[docs] 和unserialize
[docs]。
回答您的问题:不,没有内置函数可以将print_r
的输出再次解析为数组。
【讨论】:
此答案避免为所提出的问题提供解决方案。我们必须假设 OP(以及找到此页面的其他研究人员)无法修改输入结构。 (如果他们可以修改输入结构,那么 SO 上还有很多其他页面描述了如何使用serialize
/unserialize
和 json_encode()
/json_decode()
。)【参考方案3】:
对于带有子数组的数组输出,ninetwozero提供的解决方案是不行的,你可以试试这个处理复杂数组的函数:
<?php
$array_string = "
Array
(
[0] => Array
(
[0] => STATIONONE
[1] => 02/22/15 04:00:00 PM
[2] => SW
[3] => Array
(
[0] => 4.51
)
[4] => MPH
[5] => Array
(
[0] => 16.1
)
[6] => MPH
)
[1] => Array
(
[0] => STATIONONE
[1] => 02/22/15 05:00:00 PM
[2] => S
[3] => Array
(
[0] => 2.7
)
[4] => MPH
[5] => Array
(
[0] => 9.61
)
[6] => MPH
)
)
";
print_r(print_r_reverse(trim($array_string)));
function print_r_reverse(&$output)
$expecting = 0; // 0=nothing in particular, 1=array open paren '(', 2=array element or close paren ')'
$lines = explode("\n", $output);
$result = null;
$topArray = null;
$arrayStack = array();
$matches = null;
while (!empty($lines) && $result === null)
$line = array_shift($lines);
$trim = trim($line);
if ($trim == 'Array')
if ($expecting == 0)
$topArray = array();
$expecting = 1;
else
trigger_error("Unknown array.");
else if ($expecting == 1 && $trim == '(')
$expecting = 2;
else if ($expecting == 2 && preg_match('/^\[(.+?)\] \=\> (.+)$/', $trim, $matches)) // array element
list ($fullMatch, $key, $element) = $matches;
if (trim($element) == 'Array')
$topArray[$key] = array();
$newTopArray =& $topArray[$key];
$arrayStack[] =& $topArray;
$topArray =& $newTopArray;
$expecting = 1;
else
$topArray[$key] = $element;
else if ($expecting == 2 && $trim == ')') // end current array
if (empty($arrayStack))
$result = $topArray;
else // pop into parent array
// safe array pop
$keys = array_keys($arrayStack);
$lastKey = array_pop($keys);
$temp =& $arrayStack[$lastKey];
unset($arrayStack[$lastKey]);
$topArray =& $temp;
// Added this to allow for multi line strings.
else if (!empty($trim) && $expecting == 2)
// Expecting close parent or element, but got just a string
$topArray[$key] .= "\n".$line;
else if (!empty($trim))
$result = $line;
$output = implode("\n", $lines);
return $result;
/**
* @param string $output : The output of a multiple print_r calls, separated by newlines
* @return mixed[] : parseable elements of $output
*/
function print_r_reverse_multiple($output)
$result = array();
while (($reverse = print_r_reverse($output)) !== NULL)
$result[] = $reverse;
return $result;
?>
有一个小错误,如果你有一个空值(空字符串),它会嵌入到之前的值中。
【讨论】:
解决空字符串问题的快速解决方法。在函数的最顶部添加这行代码: $output = str_replace('] => '."\n", '] => [[[EMPTYSTRING]]]'."\n", $output) ;然后直接在现有的“$topArray[$key] = $element;”之前代码行,添加这一行: $element = str_replace('[[[EMPTYSTRING]]]', '', $element); 除了空值问题,对空字符串keys也不好处理,不支持stdClass Object
。【参考方案4】:
没有。但您可以同时使用serialize
和json_*
函数。
$a = array('foo' => 'fooMe');
echo serialize($a);
$a = unserialize($input);
或者:
echo json_encode($a);
$a = json_decode($input, true);
【讨论】:
OP 并没有要求其他方法来编码/序列化数据。 OP 已经声明输入是来自print_r()
的输出并且需要解析文本。【参考方案5】:
print_r
不能这样做,var_export
应该允许类似的东西,但不完全是你要求的东西
http://php.net/manual/en/function.var-export.php
$val = var_export($a, true);
print_r($val);
eval('$func_val='.$val.';');
【讨论】:
在这种情况下needed_function
是什么?
这就是 OP 发布的内容...needed_function(' Array ( [foo] => printme )');
我想他想知道这个函数是什么,以便他得到一个数组。
看在上帝的份上,永远不要在生产代码中使用eval
!
这篇文章绝不会试图解析print_r()
生成的文本——这是OP所需要的。【参考方案6】:
有一个很好的在线工具,它的名字就是这样:
print_r to json online converter
从 JSON 对象到使用 json_decode 函数创建数组不远:
要从中获取数组,请将第二个参数设置为 true。如果你不这样做,你会得到一个对象。
json_decode($jsondata, true);
【讨论】:
感谢您提供在线 JSON 转换器的链接。这就是我一直在寻找的。span> 【参考方案7】:我认为我的函数也很酷,适用于嵌套数组:
function print_r_reverse($input)
$output = str_replace(['[', ']'], ["'", "'"], $input);
$output = preg_replace('/=> (?!Array)(.*)$/m', "=> '$1',", $output);
$output = preg_replace('/^\s+\)$/m', "),\n", $output);
$output = rtrim($output, "\n,");
return eval("return $output;");
注意:最好不要将其与用户输入数据一起使用
【讨论】:
只要你没有像Array ( )
这样的空数组,这个就可以工作。简单的搜索和替换就可以解决这个限制。
不处理stdClass Object
,数字数据类型,多行字符串值,转义引号。【参考方案8】:
快速功能(不检查您是否发送了良好的数据):
function textToArray($str)
$output = [];
foreach (explode("\n", $str) as $line)
if (trim($line) == "Array" or trim($line) == "(" or trim($line) == ")")
continue;
preg_match("/\[(.*)\]\ \=\>\ (.*)$/i", $line, $match);
$output[$match[1]] = $match[2];
return $output;
这是预期的输入:
Array
(
[test] => 6
)
【讨论】:
不适用于嵌套数组。【参考方案9】:使用
var_export(array('Sample array', array('Apple', 'Orange')));
输出:
array (
0 => 'Sample array',
1 =>
array (
0 => 'Apple',
1 => 'Orange',
),
)
【讨论】:
这篇文章绝不会尝试解析print_r()
生成的文本。【参考方案10】:
这就是我对问题的解释:
function parsePrintedArray($s)
$lines = explode("\n",$s);
$a = array();
foreach ($lines as $line)
if (strpos($line,"=>") === false)
continue;
$parts = explode('=>',$line);
$a[trim($parts[0],'[] ')] = trim($parts[1]);
return $a;
适用于对象和数组:
$foo = array (
'foo' => 'bar',
'cat' => 'dog'
);
$s = print_r($foo,1);
$a = parsePrintedArray($s);
print_r($a);
输出:
Array
(
[foo] => bar
[cat] => dog
)
不适用于嵌套数组,但简单快速。
【讨论】:
不处理嵌套数组、stdClass Object
(它返回数组而不是对象)、数字数据类型、多行字符串值、以空格开头/结尾的字符串。【参考方案11】:
这是一个print_r
输出解析器,它以 PHP 语法生成相同的表达式。它是作为交互式堆栈片段编写的,因此您可以在此处使用它:
function parse(s)
const quote = s => '"' + s.replace(/["\\]/g, '\\$&') + '"';
const compress = indent => " ".repeat(((indent.length + 4) >> 3) * 4);
return "$data = " + (s.replace(/\r\n?/g, "\n") + "\n").replace(
/(Array|\w+ (Object)) *\n *\( *\n|^( *)(?:\[(?:(0|-?[1-9]\d*)|(.*?))\] => |(\) *\n+))|(-?\d+(?:\.\d+)?(?:E[-+]\d+)?)\n|(.*(?:\n(?! *\) *$| *\[.*?\] => ).*)*)\n/gm,
(_, array, object, indent, index, key, close, number, string) =>
object ? "(object) [\n"
: array ? "[\n"
: close ? compress(indent) + "],\n"
: indent ? compress(indent) + (index ?? quote(key)) + " => "
: (number ?? quote(string)) + ",\n"
).replace(/,\n$/, ";");
// I/O handling
const [input, output] = document.querySelectorAll("textarea");
(input.oninput = () => output.value = parse(input.value))();
textarea width: 23em; height: 12em
<table><tr><th>Input print_r format</th><th>Output PHP syntax</th></tr>
<tr><td><textarea>
Array
(
[0] => example
[1] => stdClass Object
(
[a[] => 1.43E+19
["] => quote
[] =>
)
)
</textarea></td><td><textarea readonly></textarea></td></tr></table>
备注
不要从原始print_r
输出中删除任何换行符。例如,Array
之后的左括号和右括号必须出现在不同的行中。
不要更改=>
周围的间距(前一个空格,后一个空格)。
因为print_r
不区分null
、""
或false
(它不会为这些值产生输出),也不区分true
和1
(两者都输出为1
) ,此转换器将永远不会产生null
、false
或true
。
由于print_r
不区分数字和字符串(9
可以表示数字或字符串),因此当存在这种歧义时,此转换器将假定数据类型为numeric .
支持stdClass Object
并转换为(object) [...]
表示法
MyClass Object
将被视为 stdClass
对象。
输出中的字符串文字是双引号,文字双引号和反斜杠被转义。
【讨论】:
【参考方案12】:json_encode()
和 json_decode()
函数会做到这一点。
$asso_arr = Array([779] => 79 => [780] => 80 [782] => 82 [783] => 83);
$to_string = json_encode($asso_arr);
它将是一个json格式"779":"79","780":"80","782":"82","783":"83"
然后我们将它转换为json_decode()
,然后它给出与原始相同的关联数组:
print_r(json_decode($to_string));
输出将是关联数组格式的Array([779] => 79 => [780] => 80 [782] => 82 [783] => 83)
。
【讨论】:
这是另一个问题的正确答案。这篇文章绝不会试图解析print_r()
生成的文本。以上是关于如何从用 print_r 打印的数组的输出创建一个数组?的主要内容,如果未能解决你的问题,请参考以下文章