如何从用 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/unserializejson_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】:

没有。但您可以同时使用serializejson_* 函数。

$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] =&gt; 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 之后的左括号和右括号必须出现在不同的行中。 不要更改=&gt; 周围的间距(前一个空格,后一个空格)。 因为print_r 不区分null""false(它不会为这些值产生输出),也不区分true1(两者都输出为1) ,此转换器将永远不会产生nullfalsetrue。 由于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] =&gt; 79 =&gt; [780] =&gt; 80 [782] =&gt; 82 [783] =&gt; 83)

【讨论】:

这是另一个问题的正确答案。这篇文章绝不会试图解析print_r()生成的文本。

以上是关于如何从用 print_r 打印的数组的输出创建一个数组?的主要内容,如果未能解决你的问题,请参考以下文章

php基础语法

PHP中输出 echo print print_r var_dump的区别与比较

php 打印数组格式化显示

php怎么输出打印

php数组的创建及操作

全面解读php-函数