I am wanting to take text input from a Form Textarea POST in PHP and iterate over each line of text and create a PHP array with the text.
The catch is I want to take lines of text that are indented with 4 spaces before them and make those lines be a sub nested array under the above array item.
I am not sure how to do this at the moment so would appreciate any ideas on it.
// basic demo to show each line of textarea post
$text = $_POST['textarea'];
foreach(explode("\n", $text) as $line) {
echo $line;
echo '<br>';
}
UPDATE
An idea so far something along the lines of this as a start maybe....
$text = $_POST['textarea'];
$in_nested_array = false;
$array = array();
foreach(explode("\n", $text) as $line) {
if($line is 4 spaces){
$in_nested_array = true;
$array[''][$line];
}else{
//if in nested array and new line is not nested, add to root array
if($in_nested_array){
}else{
$in_nested_array = false;
$array[] = $line;
}
}
}
Just a first try:
$str = <<<EOD
bar
baz
meh
lol
tuuut
moo
EOD;
function parse($lines, $depth = 0, $cur = 0)
{
$retVal = array();
for ($i = $cur; $i < count($lines); $i++)
{
$line = $lines[$i];
$lDepth = strlen($line) - strlen(ltrim($line, " "));
if ($lDepth == $depth)
{
$retVal[] = array("line" => ltrim($line, " "));
} elseif ($lDepth == $depth + 4) {
$children = parse($lines, $depth + 4, $i);
$retVal[count($retVal) - 1]["children"] = $children;
$i += count($children);
}
}
return $retVal;
}
$lines = explode("\n", $str);
echo "<pre>";
print_r(parse($lines));
Output:
Array
(
[0] => Array
(
[line] => bar
[children] => Array
(
[0] => Array
(
[line] => baz
[children] => Array
(
[0] => Array
(
[line] => meh
)
[1] => Array
(
[line] => lol
[children] => Array
(
[0] => Array
(
[line] => tuuut
)
)
)
)
)
)
)
[1] => Array
(
[line] => moo
)
)
To seperate by 4 spaces:
$txt = preg_split('/ +/', $text);
Related
i hope someone can help.
I have a string as following
$string = 'latitude=46.6781471,longitude=13.9709534,options=[units=auto,lang=de,exclude=[hourly,minutely]]';
Now what i am trying is to create an array out of each key, value pair but badly failing with regex for preg_match_all()
Currently my attempts aren't giving desired results, creating key => value pairs works as long as there are no brackets, but i have absolutely no idea how to achieve a multidimensional array if key contains key/value pairs inside brackets in example.
Array (
[0] => Array
(
[0] => latitude=46.6781471,
[1] => longitude=13.9709534,
[2] => options=[units=si,
[3] => lang=de,
)
[1] => Array
(
[0] => latitude
[1] => longitude
[2] => options=[units
[3] => lang
)
.. and so on
Where in the end i would like to achieve results as following.
Array (
[latitude] => 46.6781471
[longitude] => 13.9709534
[options] => Array
(
[units] => auto
[exclude] => hourly,minutely
)
)
I would appreciate any help or example how i can achieve this from a given string.
Regular expression isn't the right tool to deal with recursive matches. You can write a parser instead of a regex (or use JSON, query string, XML or any other commonly used format):
function parseOptionsString($string) {
$length = strlen($string);
$key = null;
$contextStack = array();
$options = array();
$specialTokens = array('[', ']', '=', ',');
$buffer = '';
$currentOptions = $options;
for ($i = 0; $i < $length; $i++) {
$currentChar = $string[$i];
if (!in_array($currentChar, $specialTokens)) {
$buffer .= $currentChar;
continue;
}
if ($currentChar == '[') {
array_push($contextStack, [$key, $currentOptions]);
$currentOptions[$key] = array();
$currentOptions = $currentOptions[$key];
$key = '';
$buffer = '';
continue;
}
if ($currentChar == ']') {
if (!empty($buffer)) {
if (!empty($key)) {
$currentOptions[$key] = $buffer;
} else {
$currentOptions[] = $buffer;
}
}
$contextInfo = array_pop($contextStack);
$previousContext = $contextInfo[1];
$thisKey = $contextInfo[0];
$previousContext[$thisKey] = $currentOptions;
$currentOptions = $previousContext;
$buffer = '';
$key = '';
continue;
}
if ($currentChar == '=') {
$key = $buffer;
$buffer = '';
continue;
}
if ($currentChar == ',') {
if (!empty($key)) {
$currentOptions[$key] = $buffer;
} else if (!empty($buffer)) {
$currentOptions[] = $buffer;
}
$buffer = '';
$key = '';
continue;
}
}
if (!empty($key)) {
$currentOptions[$key] = $buffer;
}
return $currentOptions;
}
this gives the following output:
print_r(parseOptionsString($string));
Array
(
[latitude] => 46.6781471
[longitude] => 13.9709534
[options] => Array
(
[units] => auto
[lang] => de
[exclude] => Array
(
[0] => hourly
[1] => minutely
)
)
)
Note also that you want a special syntax for arrays with only comma separated values (exclude=[hourly,minutely] becomes exclude => hourly,minutely and not exclude => array(hourly, minutely)). I think this is an inconsistency in your format and I wrote the parser with the "correct" version in mind.
If you don't want parser you can also try this code. It converts your string to JSON and decode to array. But as others said, I think you should try the approach with JSON. If you're sending this string by XmlHttpRequest in JavaScript it will not be hard to create proper JSON code to send.
$string = 'latitude=46.6781471,longitude=13.9709534,options=[units=auto,lang=de,exclude=[hourly,minutely]]';
$string = preg_replace('/([^=,\[\]\s]+)/', '"$1"', $string);
$string = '{' . $string . '}';
$string = str_replace('=', ':', $string);
$string = str_replace('[', '{', $string);
$string = str_replace(']', '}', $string);
$string = preg_replace('/({[^:}]*})/', '|$1|', $string);
$string = str_replace('|{', '[', $string);
$string = str_replace('}|', ']', $string);
$result = json_decode($string, true);
print_r($result);
I have a text file which I must read, and use the data from.
3
sam 99912222
tom 11122222
harry 12299933
sam
edward
harry
How can I create an array of these strings in the following form?
array(
"name" => "number"
...
)
I tried this:
$handle = fopen("file.txt", "r");
fscanf($handle, "%d %d", $name, $number);
What then? No matter what I try, it only works for the first line.
sam 99912222
Added codes to have both types of output - ignoring and including the lines that don't have name-value pairs. Check them out below
This code goes through each line and gets only the ones that have both name and value (something[space]something)):
//$lines = ... each line of the file in an array
$vals = array();
foreach($lines as $v){
$tmp = explode(' ', $v);
if(count($tmp) > 1){
$vals[trim($tmp[0])] = trim($tmp[1]); // trim to prevent garbage
}
}
print_r($vals);
It will output this:
Array
(
[sam] => 99912222
[tom] => 11122222
[harry] => 12299933
)
See the code in action here.
If you need the values even if they didn't come in pairs, do it like this:
//$lines = ... each line of the file
$vals = array();
foreach($lines as $v){
$tmp = explode(' ', $v);
$name = '';
$number = '';
$tmp[0] = trim($tmp[0]);
if(count($tmp) > 1){
$name = $tmp[0];
$number = trim($tmp[1]);
}else{
if(is_numeric($tmp[0])){
$number = $tmp[0];
}else{
$name = $tmp[0];
}
}
$vals[] = array(
'name' => $name,
'number' => $number
);
}
print_r($vals);
And the output:
Array
(
[0] => Array
(
[name] =>
[number] => 3
)
[1] => Array
(
[name] => sam
[number] => 99912222
)
[2] => Array
(
[name] => tom
[number] => 11122222
)
[3] => Array
(
[name] => harry
[number] => 12299933
)
[4] => Array
(
[name] => sam
[number] =>
)
[5] => Array
(
[name] => edward
[number] =>
)
[6] => Array
(
[name] => harry
[number] =>
)
See the code in action here.
Data in file are inconsistent, best of is to use regex to identify what data you've got from each line.
$lines = file('file.txt'); // this will open file and split them into lines
$items = array();
foreach($lines as $line){
$name = null;
$number = null;
$nameFound = preg_match("|([A-Za-z]+)|", $line, $matches);
if($nameFound){
$name = $matches[0];
}
$numberFound = preg_match("|([0-9]+)|", $line, $matches);
if($numberFound){
$number = $matches[0];
}
$items[] = array('name' => $name, 'number' => $number);
}
Then in items you should find parsed data from file.
To make it just extract full format data just change lines with regex into one line like this:
$lines = file('file.txt'); // this will open file and split them into lines
$items = array();
foreach($lines as $line){
$userFound = preg_match("/([A-Za-z]+) ([0-9]+)/", $line, $matches);
if($userFound){
$items[$matches[1]] = $matches[2];
}
}
With the Algorithm below, you can simply parse each individual line of the Text-File Contents into an array with the 1st Word or Digit(s) on each line as the Key and the 2nd Word as the Value. When the 2nd word or group of words do not exist, a NULL is assigned to that Key. For re-usability, this algorithm has been encapsulated into a Function. Here you go:
<?php
function parseTxtFile($txtFile){
$arrTxtContent = [];
if(!file_exists($txtFile)){ return null;}
$strFWriteTxtData = file_get_contents($txtFile);
if(empty($strFWriteTxtData)){return null;}
$arrFWriteInfo = explode("\n", $strFWriteTxtData);
foreach($arrFWriteInfo as $iKey=>$lineData){
$arrWriteData = explode(", ", $lineData);
foreach($arrWriteData as $intKey=>$strKeyInfo){
preg_match("#(^[a-z0-9_A-Z]*)(\s)(.*$)#i", $strKeyInfo, $matches);
preg_match("#(^[a-z0-9_A-Z]*)(\s*)?$#i", $strKeyInfo, $matches2);
if($matches) {
list(, $key, $null, $val) = $matches;
if (!array_key_exists($key, $arrTxtContent)) {
$arrTxtContent[$key] = $val;
}else{
$iKey = $intKey + 1;
$key = $key . "_{$iKey}";
$arrTxtContent[$key] = $val;
}
}else if($matches2) {
list(, $key, $null) = $matches2;
if (!array_key_exists($key, $arrTxtContent)) {
$arrTxtContent[$key] = null;
}else{
$key = preg_match("#_\d+#", $key, $match)? $key . $match[0] : "{$key}_1";
$arrTxtContent[$key] = null;
}
}
}
}
return $arrTxtContent;
}
var_dump(parseTxtFile(__DIR__ . "/data.txt"));
Just call the function parseTxtFile($txtFile) passing it the path to your text File and it will return an Array that looks something like below:
array (size=7)
3 => null
'sam' => string '99912222' (length=8)
'tom' => string '11122222' (length=8)
'harry' => string '12299933' (length=8)
'sam_1' => null
'edward' => null
'harry_1' => null
Hope this could help a bit....
Cheers & Good-Luck ;-)
I need to get numbers as an array from a given string.
Example string:
$t = '1-P,2-T,3-P,4-R,5-C,6-T,';
Expected output:
if I search -T the output needs to be like this:
array(
[0] => 2,
[1] => 6
)
if it's -P:
array(
[0] => 1,
[1] => 3
)
I tried var_export(explode("-T,",$t)); but it didn't work as expected.
Can any one give me a suggestion to get this?
The below matches the full integer number which preceeds the search term -P.
Let's keep it concise:
$matches = array();
if (preg_match_all('/([0-9]+)\-P/', $t, $matches) >= 1) {
var_dump($matches[1]);
}
Search for '/([0-9]+)\-P/, '/([0-9]+)\-C/, '/([0-9]+)\-T/ an so on.
A more dynamic way to look for different search terms/filters:
$filter = '-T';
$pattern = sprintf('/([0-9]+)%s/', preg_quote($filter));
See preg_match_all and preg_quote functions.
Try this:
$t = '211111111131-P,2-T,3654554-P,4-R,5-C,6-T,';
$find = "-P"; // Search element
$found = []; // Result array
$array = explode(",", $t); // Breaking up into array
foreach($array as $arr) {
if (strpos($arr, $find)) { // Checking if search element is found in $arr
$found[] = explode('-',$arr)[0]; // Extracting the number prefix e.g 1 for 1-P
}
}
Output:
Array
(
[0] => 1
[1] => 3
)
Use it as
$t = '1-P,2-T,3-P,4-R,5-C,6-T,';
$data = explode(",", $t);
print_r($data);
$row=array();
for ($i = 0; $i <= count($data); $i++) {
if (!empty($data[$i])) {
if (strpos($data[$i], '-T') !== false) {// pass find value here
$final = explode("-", $data[$i]);
$row[]=$final[0];
}
}
}
print_r($row);
Output
Array
(
[0] => 2
[1] => 6
)
DEMO
$t = '1-P,2-T,3-P,4-R,5-C,6-T,';
$temp = [];
// if the last comma is not typo the 3rd argument `-1` omit empty item
$array = explode(",", $t, -1);
foreach($array as $arr) {
list($v, $k) = explode('-', $arr);
$temp[$k][] = $v;
}
print_r($temp['T']);
demo
Lots of good answers here already, but none take the approach of first putting the data into a better structure.
The code below converts the data to an associative array mapping letters to arrays of numbers, so that you can then do repeated lookups by whichever letter you want:
$t = '1-P,2-T,3-P,4-R,5-C,6-T,';
$a = array_filter(explode(',', $t));
$map = [];
foreach($a as $item) {
$exploded = explode('-', $item);
$number = $exploded[0];
$letter = $exploded[1];
if (!array_key_exists($letter, $map)) {
$map[$letter] = [];
}
$map[$letter][] = $number;
}
print_r($map);
// Array
// (
// [P] => Array
// (
// [0] => 1
// [1] => 3
// )
//
// [T] => Array
// (
// [0] => 2
// [1] => 6
// )
//
// [R] => Array
// (
// [0] => 4
// )
//
// [C] => Array
// (
// [0] => 5
// )
//
// )
print_r($map['T']);
// Array
// (
// [0] => 2
// [1] => 6
// )
print_r($map['P']);
// Array
// (
// [0] => 1
// [1] => 3
// )
I have this array
dev3->content->->mktg->->->pls1->->->pls2->->->config->->splash
I want to convert this string to multidimensional array. like this
Array
(
[0] => dev3
Array (
[0] => ->content
Array (
[0] => ->->mktg
Array(
[0] => ->->->pls1
[1] => ->->->pls2
[2] => ->->->config
)
[1] => ->->splash
)
)
)
Can anyone do this
it does not work if level will be increaed more then +1 on any step
$str = 'dev3->content->->mktg->->->pls1->->->pls2->->->config->->splash';
$in = preg_split('/(?<!>)(?=->)/', $str);
Above we make such array from the input string
Array
(
[0] => dev3
[1] => ->content
[2] => ->->mktg
[3] => ->->->pls1
[4] => ->->->pls2
[5] => ->->->config
[6] => ->->splash
)
continue working
$result = [];
$p = &$result;
$level = 0;
foreach($in as $i) {
// Count next level
$c = substr_count($i, '->');
// if level is not changed
if($c == $level) { $p[] = $i; continue; }
// level increased
if ($c == $level + 1) {
$level++;
$p[] = [$i];
$p = &$p[count($p)-1];
continue;
}
// any level less then achived before
if ($c < $level) {
$p = &$result;
$level = $c;
while($c--)
$p = &$p[count($p)-1];
$p[] = $i;
continue;
}
die("I can't process this input string");
}
print_r($result);
working demo
I have this file format of txt file generated from schematic software:
(
NETR5_2
R6,1
R5,2
)
(
NETR1_2
R4,2
R3,1
R3,2
R2,1
R2,2
R1,1
R1,2
)
I need to get this:
Array
(
[0] => Array
(
[0] => NETR5_2
[1] => R6,1
[2] => R5,2
)
[1] => Array
[0] => NETR1_2
[1] => R4,2
[2] => R3,1
[3] => R3,2
[4] => R2,1
[5] => R2,2
[6] => R1,1
[7] => R1,2
)
Here is code i try but i get all from input string:
$file = file('tangoLista.txt');
/* GET - num of lines */
$f = fopen('tangoLista.txt', 'rb');
$lines = 0;
while (!feof($f)) {
$lines += substr_count(fread($f, 8192), "\n");
}
fclose($f);
for ($i=0;$i<=$lines;$i++) {
/* RESISTORS - check */
if (strpos($file[$i-1], '(') !== false && strpos($file[$i], 'NETR') !== false) {
/* GET - id */
for($k=0;$k<=10;$k++) {
if (strpos($file[$i+$k], ')') !== false || empty($file[$i+$k])) {
} else {
$json .= $k.' => '.$file[$i+$k];
}
}
$resistors_netlist[] = array($json);
}
}
echo '<pre>';
print_r($resistors_netlist);
echo '</pre>';
I need to read between ( and ) and put into array values...i try using checking if line begins with ( and NETR and if yes put into array...but i don't know how to get number if items between ( and ) to get foreach loop to read values and put into array.
Where i im making mistake? Can code be shorter?
Try this approach:
<?php
$f = fopen('test.txt', 'rb');
$resistors_netlist = array();
$current_index = 0;
while (!feof($f)) {
$line = trim(fgets($f));
if (empty($line)) {
continue;
}
if (strpos($line, '(') !== false) {
$resistors_netlist[$current_index] = array();
continue;
}
if (strpos($line, ')') !== false) {
$current_index++;
continue;
}
array_push($resistors_netlist[$current_index], $line);
}
fclose($f);
print_r($resistors_netlist);
This gives me:
Array
(
[0] => Array
(
[0] => NETR5_2
[1] => R6,1
[2] => R5,2
)
[1] => Array
(
[0] => NETR1_2
[1] => R4,2
[2] => R3,1
[3] => R3,2
[4] => R2,1
[5] => R2,2
[6] => R1,1
[7] => R1,2
)
)
We start $current_index at 0. When we see a (, we create a new sub-array at $resistors_netlist[$current_index]. When we see a ), we increment $current_index by 1. For any other line, we just append it to the end of $resistors_netlist[$current_index].
Try this, using preg_match_all:
$text = '(
NETR5_2
R6,1
R5,2
)
(
NETR1_2
R4,2
R3,1
R3,2
R2,1
R2,2
R1,1
R1,2
)';
$chunks = explode(")(", preg_replace('/\)\W+\(/m', ')(', $text));
$result = array();
$pattern = '{([A-z0-9,]+)}';
foreach ($chunks as $row) {
preg_match_all($pattern, $row, $matches);
$result[] = $matches[1];
}
print_r($result);
3v4l.org demo
I'm not the king of regex, so you can find a better way.
The main problem are parenthesis: I don't know what are between closing and next open parenthesis ( )????( ), so first I replace every space, tab, cr or ln between, then I explode the string by )(.
I perform a foreach loop for every element of resulted array, matching every occurrence of A-z0-9, and add array of retrieved values to an empty array that, at end of foreach, will contain desired result.
Please note:
The main pattern is based on provided example: if the values contains other characters then A-z 0-9 , the regex fails.
Edit:
Replaced preliminar regex pattern with `/\)\W+\(/m`