0

Hope someone can point me in the right direction here...

I've got directory paths and partial file outputs form a unix grep. I have a flat array from these outputs. Now I'd like to do a bit of PHP magic to turn this flat array into a more hierarchical multidimensional array for more refined user output

Current array;

array(7) {
  [0]=>
  string(160) "/home/user/data/section1/dir1/20120107/filename.txt:random text after the colon"
  [1]=>
  string(160) "/home/user/data/section1/dir1/20120108/filename.txt: More random text after the colon"
  [2]=>
  string(160) "/home/user/data/section1/dir2/20120107/filename.txt: More random text after the colon"
  [3]=>
  string(160) "/home/user/data/section1/dir2/20120108/filename.txt: More random text after the colon"
  [4]=>
  string(160) "/home/user/data/section1/dir3/20120107/filename.txt: More random text after the colon"
  [5]=>
  string(160) "/home/user/data/section1/dir3/20120106/filename.txt: More random text after the colon"
  [6]=>
  string(160) "/home/user/data/section1/dir3/20120108/filename.txt: More random text after the colon"
}

What i would really like

array(1) {
    array(3) {
        ["dir"]=>
        string(4) "dir1"
        ["date"]=>
        string(8) "20120107"
        ["text"]=>
        array (2) {
          [0]=>
          string(160) "random text after the colon"
          [1]=>
          string(160) "More random text after the colon"
          }
    }
    array(3) {
        ["dir"]=>
        string(4) "dir1"
        ["date"]=>
        string(8) "20120108"
        ["text"]=>
        array (2) {
          [0]=>
          string(160) "More random text after the colon"
          [1]=>
          string(160) "More random text after the colon"
          }
    }
    array(3) {
        ["dir"]=>
        string(4) "dir2"
        ["date"]=>
        string(8) "20120107"
        ["text"]=>
        array (2) {
          [0]=>
          string(160) "More random text after the colon"
          [1]=>
          string(160) "More random text after the colon"
          }
    }
}

I have tried a lot of foreach's, SPL iterator methods, but i'm just not coming out trumps. Looking for any guidance.

Thanks all

2
  • Can you post what you have tried. Commented May 18, 2012 at 9:25
  • 1
    It's not clear why you have two "random" strings for each entry... Commented May 18, 2012 at 9:37

6 Answers 6

2

This code (using a for loop):

<?php
$data[] = "/home/user/data/section1/dir1/20120107/filename.txt:random text after the colon";
$data[] = "/home/user/data/section1/dir1/20120108/filename.txt: More random text after the colon";
$data[] = "/home/user/data/section1/dir2/20120107/filename.txt: More random text after the colon";
$data[] = "/home/user/data/section1/dir2/20120108/filename.txt: More random text after the colon";
$data[] = "/home/user/data/section1/dir3/20120107/filename.txt: More random text after the colon";
$data[] = "/home/user/data/section1/dir3/20120106/filename.txt: More random text after the colon";
$data[] = "/home/user/data/section1/dir3/20120108/filename.txt: More random text after the colon";

for($i = 0; $i < count($data); $i++) {
    $data[$i] = str_replace('/home/user/data/section1/','',$data[$i]);
    $tmp = explode('/', $data[$i]);

    $newData[$i] = array(
        'dir' => $tmp[0],
        'date' => $tmp[1]
    );

    $tmp = explode(':', $tmp[2]);

    $newData[$i]['fileName'] = $tmp[0];
    $newData[$i]['text'] = $tmp[1];
}

print_r($newData);
?>

Or this code (using a foreach loop):

<?php
$data[] = "/home/user/data/section1/dir1/20120107/filename.txt:random text after the colon";
$data[] = "/home/user/data/section1/dir1/20120108/filename.txt: More random text after the colon";
$data[] = "/home/user/data/section1/dir2/20120107/filename.txt: More random text after the colon";
$data[] = "/home/user/data/section1/dir2/20120108/filename.txt: More random text after the colon";
$data[] = "/home/user/data/section1/dir3/20120107/filename.txt: More random text after the colon";
$data[] = "/home/user/data/section1/dir3/20120106/filename.txt: More random text after the colon";
$data[] = "/home/user/data/section1/dir3/20120108/filename.txt: More random text after the colon";

foreach($data as $d) {
    $tmp = explode('/', str_replace('/home/user/data/section1/','',$d));
    $tmp2 = explode(':', $tmp[2]);

    $newData[] = array(
        'dir' => $tmp[0],
        'date' => $tmp[1],
        'filename' => $tmp2[0],
        'text' => $tmp2[1]
    );
}

print_r($newData);
?>

Outputs:

Array
(
    [0] => Array
        (
            [dir] => dir1
            [date] => 20120107
            [fileName] => filename.txt
            [text] => random text after the colon
        )

    [1] => Array
        (
            [dir] => dir1
            [date] => 20120108
            [fileName] => filename.txt
            [text] =>  More random text after the colon
        )

============ more data here ============

    [6] => Array
        (
            [dir] => dir3
            [date] => 20120108
            [fileName] => filename.txt
            [text] =>  More random text after the colon
        )

)
Sign up to request clarification or add additional context in comments.

2 Comments

Good, but why the for loop instead of a foreach?
No reason, I've added a foreach example now too :)
0

Explode each string of path with "/".You will get an array after that.Then push required element in the array.

Comments

0

Make a foreach over the first array and preg_match() the elements for the informations you want to extract from each string.

foreach( $firstArray => $strElement )
{
   $newArray[] = array();

   if( preg_match( "~(?<=section1/)[.-\w]*~i", $strElement, $astrMatches) >= 1 )
     $newArray['dir'] = $astrMatches[0];
   ...etc...
}

Comments

0
function magic($array_of_strings)
{
    define('REGEX','_^/home/user/data/section1/(dir\d+)/(\d+)/filename.txt:(.*)$_');
    $ret_array = array();

    foreach($array_of_strings as $string) {
        if (preg_match(REGEX, $string, $matches)) {
            $ret_array []= array(
              'dir'=>$matches[1],
              'date'=>$matches[2],
              'text'=>$matches[3],
            );
        }
    }
    return $ret_array;
}

Comments

0

Ok this will do the job, you can change the directory structure as much as you like as long as the the last two directories keep the same order /dir/date.

You can add as many strings as you like to the text section of the array by seperating them with multiple colons after the URL. e.g. /blah/dir/date/filename.txt : string 1 : string 2.

Your original array must be called $array.

Enjoy:

foreach ($array as $string) {
   $temp = array();
   $temp["strings"] = explode(':', $string); //Convert the string into an array using `:` as a seperator
   $temp["path"] = explode('/', $temp["strings"][0]); //Convert the url into an array using `/` as a seperator (each directory is it's own entry)
   $path_count = count($temp["path"]); //Count number of directories in the url
   $output = array(
      "dir" => $temp["path"][$path_count - 3],
      "date" => $temp["path"][$path_count - 2],
      "text" => array()
   );
   foreach ($temp["strings"] as $index => $value) { //Loop through and add any additional text to array
      if ($index) {
         array_push($output["text"], trim($value));
      }      
   }
   print_r($output);
}

Comments

0

Thanks all for the input and scripts. I have actually learned quite a bit about massaging data into multidimensional arrays from these scripts. Unfortunately, none of them worked out exactly as i wanted. One thing i've learned researching this issue, is, 'is there another way to present the data?' and in this case i found it. A shell script, to search all files, output the filename, and then the relevant text.

find /home/user/data/section1 -name 'filename.txt' | xargs grep -il texttxet | 
   while read file 
       do
          echo "$file"
          grep -i  -A 4 texttxet "$file" 
       done

File:/home/user/data/section1/dir1/20120107/filename.txt
line1
line2
line3

File:/home/user/data/section1/dir1/20120108/filename.txt
line1
line2

File:/home/user/data/section1/dir2/20120108/filename.txt
line1
line2

I can easily get this info in an array from this point. Thanks all again

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.