1

I am writing a php code to search for different variables in a text file....

The data is listed line by line in a flatfile and the format for data listing is:

date | time | ip | geo-location (city) | //url

The data is saved as a logfile ('track-log.txt')

The code I have so far is:

$log_file = file_get_contents('track-log.txt');

$log_lines = explode(PHP_EOL, $log_file);

$log_lines = array_flip($log_lines);

unset($log_file);

this breaks down the text file into lines, then flips the lines backwards, so that they are listed in the array $log_lines[*] as last line in text file displayed first as $log_lines[0]

I need to count how many occurrences of "date" there are that are the same....

<..... lots of logs here .... then .....>

jan 1st 2012 | data.....
jan 1st 2012 | data ....
jan 1st 2012 | data ....
jan 1st 2012 | data ....
jan 1st 2012 | data ....
jan 2nd 2012 | data ....
jan 2nd 2012 | data ....
jan 2nd 2012 | data .... <end log>

Imagine this is the end of the log.... I would like:

$count[0] = 3 // last 3x dates are the same
$count[1] = 5 // the 5x dates before that are the same

So I can use

echo $count[0];

To display the amount of most recent values in the "date" part of the log.

I would like the array $count[*] to stop listing @ 7 strings....

$count[0]; ... up to ... $count[6]

Which will display the page counts of the last 7 days of logs

....

extra info.... the date format of each line in the logs is

sunday, january 22, 2012 | 16:14:36 | 82.**.***.*** | bolton | //page_url

And the date format is always the same as it is a script that writes each date on each log line

....

Cœur
  • 37,241
  • 25
  • 195
  • 267
DJ-P.I.M.P
  • 105
  • 2
  • 6
  • 15
  • Your startup code is incorrect. [`array_flip`](http://php.net/manual/en/function.array-flip.php) exchanges keys and values. All you need is `$lines=file('track-log.txt'); $lines=array_reverse($lines);` – Francis Avila Jan 23 '12 at 14:57
  • i need the explode command, to split the main input string line by line..... unless you have a better way of coding this....? – DJ-P.I.M.P Jan 23 '12 at 15:35
  • The `file()` function gives you an array of lines. No need for `explode()`. – Francis Avila Jan 23 '12 at 15:38

3 Answers3

1

that function changes the key and the value and do not reverse the array ..

 $log_lines = array_flip($log_lines);

do it that way

$log_lines = array_reverse($log_lines);

generate the count array

$count = array();
$index = -1;
$last_date = false;
foreach ($log_lines as $lines) {
     //sunday, january 22, 2012 | 16:14:36 | 82.**.***.*** | bolton | //page_url
     list($date,) = explode("|",$lines,2); //extract date 

     if ($last_date == $date)
          $count[$index]++;
     else {
         $last_date = $date;
         $index++;
         if ($index>=7) break; // 8. Date -> break
         $count[$index] = 1;
     }
}
rauschen
  • 3,956
  • 2
  • 13
  • 13
  • +1 to rauchen for (a) catching the array_reverse error first, (b) catching premature break clause in both my and Leonard's original answers, and (c) using the limit parameter in the explode clause (which might be overkill on optimization, but is still good practice and on flatfiles with long log entries could make a difference). I still prefer my approach (using the date as the unique key directly and then array_value-ing at the end), but this is just as good and a better overall answer. – Ben D Jan 23 '12 at 15:30
0

This should so the trick...

<?php

$log_file = file_get_contents('track-log.txt');
$log_lines = explode(PHP_EOL, $log_file);
$log_lines = array_reverse($log_lines);
unset($log_file);
$count = array();
//loop through and itterate the count array using the date as the unique key
foreach($log_lines as $line){
    //explode this so we can use the date segment as a key
    $pieces = explode('|',$line);
    if (!isset($count[$pieces[0]])){
        //break out if we've hit the cap size
        if (count($count)>=7){break;}
        $count[$pieces[0]] = 0; 
    }
    $count[$pieces[0]]++;

}
//switch to a numeric index
$count = array_values($count);

?>
Ben D
  • 14,321
  • 3
  • 45
  • 59
  • you count the 7. day only once even if it is there 5 times – rauschen Jan 23 '12 at 15:04
  • Good catch rauschen. I've edited accordingly (moved the break condition into the element creation step. – Ben D Jan 23 '12 at 15:10
  • dang!! I had already edited the first version to remove that! Thanks again :) – Ben D Jan 23 '12 at 15:19
  • minor problem with coding.... as script to write data lines writes data then new line character, the script you wrote counts $count[0] as a blank line, and lists value "1" .... changed (count($count)>=7) to 8, and miss out array $count[0] , just use 1 - 7 and it works perfect thanks – DJ-P.I.M.P Jan 23 '12 at 17:21
  • You might also trim() the log content to remove trailing/leading lines. Glad it's working – Ben D Jan 23 '12 at 19:22
0

Here is a functional approach to your problem.

$lines = file('track-log.txt');

// This is a group discriminator
// It must return a 'key' which is what to group by,
// (in this case, by column 1 of the input line).
// as well as the orginal value.
function col1group($line){
    $key = trim(current(explode('|', $line, 2)));
    return array($key=>$line);
}

// $grouper is the group-descriminator function.
// we generate a new array with our keys to group by, then group them by
// key with array_merge_recursive
function array_groupby($array, $grouper) {
    return call_user_func_array('array_merge_recursive', array_map($grouper, $array));
}

//This is all lines, in file order, grouped by date.
$linesbydate = array_groupby($lines, 'col1group');

// if you want just the last seven:
$last7dates = array_slice($linesbydate, -7);
// if you want numeric keys:
$last7groups = array_values($last7dates);
// if you want them in reverse order:
$last7groupsReversed = array_reverse($last7groups);

// desired output
var_dump($last7groupsReversed);

Using the sample lines you gave this program will output:

array(2) {
  [0]=>
  array(3) {
    [0]=>
    string(25) "jan 2nd 2012 | data ....
"
    [1]=>
    string(25) "jan 2nd 2012 | data ....
"
    [2]=>
    string(25) "jan 2nd 2012 | data ....
"
  }
  [1]=>
  array(5) {
    [0]=>
    string(25) "jan 1st 2012 | data.....
"
    [1]=>
    string(25) "jan 1st 2012 | data ....
"
    [2]=>
    string(25) "jan 1st 2012 | data ....
"
    [3]=>
    string(25) "jan 1st 2012 | data ....
"
    [4]=>
    string(25) "jan 1st 2012 | data ....
"
  }
}

If you need to group by some other criteria, you can do so by creating another function like col1group() and passing that to array_groupby(). You can also change the line itself in this function (e.g. calling rtrim() to remove newlines).

Francis Avila
  • 31,233
  • 6
  • 58
  • 96
  • hi francis i have error listing set on, but when i use your code i just get a blank page? sorry – DJ-P.I.M.P Jan 23 '12 at 16:40
  • No problems here. I have appended my output to the answer. Do you at least understand the code? – Francis Avila Jan 23 '12 at 17:30
  • yes i understand the code, but it wouldnt work, but one of the other answers to this question worked and i have now finished todays script..... ill probably start work on next one tonite aswell lol thanks anyways mate – DJ-P.I.M.P Jan 23 '12 at 18:55