This question already has answers here:
How create an array from the output of an array printed with print_r?
(11 answers)
Closed 10 years ago.
How can i create variable from it's print_r output ? In other words, i'd like to know if something similar to my fictive var_import function exists in php ? var_import would be the inverse of var_export
He is a use case:
$a = var_import('Array ( [0] => foo [1] => bar )');
$output = var_export($a);
echo $output; // Array ( [0] => foo [1] => bar )
If such a function does not exist, is there a tool (or online tool) to do this ?
I am also interested to do the same with var_dump output.
EDIT: The variable is only available as a print_r output (string). To clarify what i need, imagine the folowing situation: someone posts a some sample on the internet somewhere with a print_r output. To test his code, you need to import his print_r variable into your code. This is an example where var_import would be usefull.
Amusingly the PHP manual contains an example that tries to recreate the original structure from the print_r output:
print_r_reverse()
http://www.php.net/manual/en/function.print-r.php#93529
However it does depend on whitespace being preserved. So you would need the actual HTML content, not the rendered text to pipe it back in.
Also it doesn't look like it could understand anything but arrays, and does not descend. That would be incredibly difficult as there is no real termination marker for strings, which can both contain newlines and ) or even [0] and => which could be mistaken for print_r delimiters. Correctly reparsing the print_r structure would be near impossible even with a recursive regex (and an actual parser) - it could only be accomplished by guesswork splitting like in the code linked above.. (There are two more versions there, maybe you have to try them through to find a match for your specific case.)
Why don't you use var_export instead ?
var_export(array(1, 2, 3)); // array(1, 2, 3)
You can import var_export's output with eval(), however I would recommend you to avoid this function as much as possible.
The following functions are better for exporting and importing variables:
serialize() and unserialize():
$string = serialize(array(1, 2, 3));
$array = unserialize($string); // array(1, 2, 3);
Or json_encode() and json_decode():
$string = json_encode(array(1, 2, 3));
$array = json_decode($string);
You can wrap it in an output buffer:
ob_start();
print_r(array(1,2,3));
$arr = ob_get_clean();
echo $arr;
Ok so I misunderstood the first question. I think I have another solution which actually does answer your question:
<?php
$ar = array('foo','bar');
$p = print_r($ar, true);
$reg = '/\[([0-9]+)\] \=\> ([a-z]+)/';
$m = preg_match_all($reg, $p, $ms);
$new_ar = $ms[2];
echo "Your wanted result:\n";
print_r($new_ar);
If you want to import a var_export()'s variable, you can run the eval() function.
Or if you save the contents into a file (with a return statement), you can use the return value of include() or require().
But I would rather use serialize() and unserialize() or json_encode() and json_decode().
define('EXPORT_JSON', 1);
define('EXPORT_SERIALIZE', 2);
function exportIntoFile($var, $filename, $method=EXPORT_JSON)
{
if ( $method & EXPORT_JSON )
file_put_contents( $filename, json_encode($var) );
else if ($method & EXPORT_SERIALIZE)
file_put_contents( $filename, serialize($var) );
}
function importFromFile($filename, $method=EXPORT_JSON)
{
if ( $method & EXPORT_JSON )
return json_decode( file_get_contents($filename) );
else if ($method & EXPORT_SERIALIZE)
return unserialize( file_get_contents($filename) );
}
I'm not good at regex to code the final trash removal. Here is how far I could get though:
$str = 'Array ( [0] => foo [1] => bar [2] => baz)';
$t1 = explode('(', $str);
$t2 = explode(')', $t1[1]);
$t3 = explode(' => ', $t2[0]);
unset($t3[0]);
print_r($t3);
output:
Array
(
[1] => foo [1]
[2] => bar [2]
[3] => baz
)
Related
Suppose I've got the following string:
) [6] => Array ( [2014-05-05 00:0] => My actual content
If I want to only be left with My actual content at the end, what is the best way to split the entire string?
Note: the words My actual content are and can change. I'm hoping to cut the string based on the second => string as this will be present at all times.
It seems you're just looking to find the first value of an array with keys you do not know. This is super simple:
Consider the following array:
$array = array(
'2014-05-22 13:36:00' => 'foo',
'raboof' => 'eh',
'qwerty' => 'value',
'8838277277272' => 'test'
);
Method #1:
Will reset the array pointer to the first element and return it.
Using reset:
var_dump( reset($array) ); //string(3) "foo"
DEMO
Method #2:
Will reset the entire array to use keys of 0, 1, 2, 3...etc. Useful if you need to get more than one value.
Using array_values:
$array = array_values($array);
var_dump( $array[0] ); //string(3) "foo"
DEMO
Method #2.5:
Will reset the entire array to use keys of 0, 1, 2, 3...etc and select the first one into the $content variable. Useful if you need to get more than one value into variables straight away.
Using list and array_values:
list( $content ) = array_values($array);
var_dump( $content ); //string(3) "foo"
DEMO
Method #3:
Arrays are iteratable, so you could iterate through it but break out immediately after the first value.
Using a foreach loop but break immediatly:
foreach ($array as $value) {
$content = $value;
break;
}
var_dump($content); //string(3) "foo"
DEMO
To Answer your question, on extracting from a string based on last 'needle'...
Okay, this is quite an arbitrary question, since it seems like you're showing us the results from a print_r(), and you could reference the array key to get the result.
However, you mentioned "... at the end", so I'm assuming My actual content is actually right at the end of your "String".
In which case there's a very simple solution. You could use: strrchr from the PHP manual - http://www.php.net/manual/en/function.strrchr.php.
So you're looking at this: strrchr($string, '=>');
Hope this answers your question. Advise otherwise if not please.
you have to use foreach loop in a foreach to get the multi dimentional array values.
foreach($value as $key){
foreach($key as $val){
echo $val;
}
}
I have an array of the format
array(
[0]=>x_4556v_7889;
[1]=>y_9908;
[2]=>f_5643u_7865;
)
I need to get output as
array(
[0]=> ([0] =>4556;
[1] =>7889;
)
[1]=>( [0]=>9908;)
[2] =>([0] =>5643;
[1]=>7865;
)
)
how to use strpos and find out the occurance of "_"(underscore) in string and get the next four characters in for loop.
Am getting only the first four digit code the next four digit are not getting.Kindly provide some logic.
Looks like you're trying to find all the numbers. In that case, consider trying this:
$output = array_map(function($item) {
preg_match_all("/\d+/",$item,$m);
return $m[0];
},$input);
Should work just fine :)
This is a regex free solution though..
$arr = array(
0=>'x_4556v_7889;',
1=>'y_9908;',
2=>'f_5643u_7865;'
);
$lettersarr = range('a','z');
array_unshift($lettersarr,'_');
array_unshift($lettersarr,';');
$new_arr=array_map(function ($v) use($lettersarr) {
return explode('#',wordwrap(str_replace($lettersarr,'',$v), 4, "#", true)); },$arr);
print_r($new_arr);
Demonstration
I have a string like this
$php_string = '$user["name"] = "Rahul";$user["age"] = 12;$person["name"] = "Jay";$person["age"] = 12;';
or like this
$php_string = '$user = array("name"=>"Rahul","age"=>12);$person= array("name"=>"Jay","age"=>12);';
I need to get the array from the string ,
Expected result is
print_r($returned);
Array
(
[name] => Rahul
[age] => 12
)
Please note that there may be other contents on the string including comments,other php codes etc
Instead of relying on some magical regular expression, I would go a slightly easier route and use token_get_all() to tokenize the string and create a very basic parser that can create the necessary structures based on both array construction methods.
I don't think many people have rolled this themselves but it's likely the most stable solution.
use a combination of eval and preg_match_all like so:
if(preg_match_all('/array\s*\(.*\)/U', $php_string, $arrays)){
foreach($arrays as $array){
$myArray = eval("return {$array};");
print_r($myArray);
}
}
That will work as long as your array doesn't contain ) but can be modified further to handle that case
or as Jack suggests use token_get_all() like so:
$tokens = token_get_all($php_string);
if(is_array($tokens)){
foreach($tokens as $token){
if($token[0] != T_ARRAY)continue;
$myArray = eval("return {$token[1]};");
print_r($myArray);
}
}
I got a question...
I got code like this, and I want to read it with PHP.
NAME
{
title
(
A_STRING
);
settings
{
SetA( 15, 15 );
SetB( "test" );
}
desc
{
Desc
(
A_STRING
);
Cond
(
A_STRING
);
}
}
I want:
$arr['NAME']['title'] = "A_STRING";
$arr['NAME']['settings']['SetA'] = "15, 15";
$arr['NAME']['settings']['SetB'] = "test";
$arr['NAME']['desc']['Desc'] = "A_STRING";
$arr['NAME']['desc']['Cond'] = "A_STRING";
I don't know how I should start :/. The variables aren't always the same.
Can someone give me a hint on how to parse such a file?
Thx
This looks like a real grammar - you should use a parser generator. This discussion should get you started.
There are a few options already made for php: a lexer generator module and this is a parser generator module.
It's not an answer but suggestion:
Maybe you can modify your input code to be compatible with JSON which has similar syntax. JSON parsers and generators are available for PHP.
http://www.json.org/
http://www.php.net/json
If the files are this simple, then rolling your own homegrown parser is probably a lot easier. You'll eventually end up writing regex with lexers anyway. Here's a quick hack example: (in.txt should contain the input you provided above.)
<pre>
<?php
$input_str = file_get_contents("in.txt");
print_r(parse_lualike($input_str));
function parse_lualike($str){
$str = preg_replace('/[\n]|[;]/','',$str);
preg_match_all('/[a-zA-Z][a-zA-Z0-9_]*|[(]\s*([^)]*)\s*[)]|[{]|[}]/', $str, $matches);
$tree = array();
$stack = array();
$pos = 0;
$stack[$pos] = &$tree;
foreach($matches[0] as $index => $token){
if($token == '{'){
$node = &$stack[$pos];
$node[$ident] = array();
$pos++;
$stack[$pos] = &$node[$ident];
}elseif($token=='}'){
unset($stack[$pos]);
$pos--;
}elseif($token[0] == '('){
$stack[$pos][$ident] = $matches[1][$index];
}else{
$ident = $token;
}
}
return $tree;
}
?>
Quick explanation: The first preg_replace removes all newlines and semicolons, as they seem superfluous. The next part divides the input string into different 'tokens'; names, brackets and stuff inbetween paranthesis. Do a print_r $matches; there to see what it does.
Then there's just a really hackish state machine (or read for-loop) that goes through the tokens and adds them to a tree. It also has a stack to be able to build nested trees.
Please note that this algorithm is in no way tested. It will probably break when presented with "real life" input. For instance, a parenthesis inside a value will cause trouble. Also note that it doesn't remove quotes from strings. I'll leave all that to someone else...
But, as you requested, it's a start :)
Cheers!
PS. Here's the output of the code above, for convenience:
Array
(
[NAME] => Array
(
[title] => A_STRING
[settings] => Array
(
[SetA] => 15, 15
[SetB] => "test"
)
[desc] => Array
(
[Desc] => A_STRING
[Cond] => A_STRING
)
)
)
Before I write my own function to do it, is there any built-in function, or simple one-liner to convert:
Array
(
[0] => pg_response_type=D
[1] => pg_response_code=U51
[2] => pg_response_description=MERCHANT STATUS
[3] => pg_trace_number=477DD76B-B608-4318-882A-67C051A636A6
)
Into:
Array
(
[pg_response_type] => D
[pg_response_code] =>U51
[pg_response_description] =>MERCHANT STATUS
[pg_trace_number] =>477DD76B-B608-4318-882A-67C051A636A6
)
Just trying to avoid reinventing the wheel. I can always loop through it and use explode.
I can always loop through it and use explode.
that's what you should do.
Edit - didn't read the question right at all, whoops..
A foreach through the array is the quickest way to do this, e.g.
foreach($arr as $key=>$val)
{
$new_vals = explode("=", $val);
$new_arr[$new_vals[0]] = $new_vals[1];
}
This should be around five lines of code. Been a while since I've done PHP but here's some pseudocode
foreach element in the array
explode result on the equals sign, set limit = 2
assign that key/value pair into a new array.
Of course, this breaks on keys that have more than one equals sign, so it's up to you whether you want to allow keys to have equals signs in them.
You could do it like this:
$foo = array(
'pg_response_type=D',
'pg_response_code=U51',
'pg_response_description=MERCHANT STATUS',
'pg_trace_number=477DD76B-B608-4318-882A-67C051A636A6',
);
parse_str(implode('&', $foo), $foo);
var_dump($foo);
Just be sure to encapsulate this code in a function whose name conveys the intent.