0

My subject looks like this:

[9] 20:30:40 [SUCCESS] s-a24:1337
2
8.87
4038047
35320
4002727
[10] 20:30:40 [SUCCESS] s-d28:1337
2
2.64
4038047
37363
4000684
[11] 20:30:40 [SUCCESS] s-b29:1337
2
0.56
4038047
33066
4004981
[66] 20:30:42 [FAILURE] s-b25:1337 Timed out, Killed by signal 9
2
1.16
4038047
35274
[67] 20:30:42 [FAILURE] s-b30:1337 Timed out, Killed by signal 9

I need to create a multi-dimentional array that will match

  • success/failure
  • descriptor (s-a24, s-d28, etc)
  • 5 rows of numbers that follow (can be any length)

There could be anywhere from 0 to 5 rows (5 rows is SUCCESS)

I'm absolutely inept in regex

What I started with is this, it does not work.

preg_match_all("/\[[0-9]+\](.*?)\[[0-9]+\]/",$output,$array);
  • Is that whole block a single string? – Jack Apr 20 '12 at 00:49
  • See [Open source RegexBuddy alternatives](http://stackoverflow.com/questions/89718/is-there) and [Online regex testing](http://stackoverflow.com/questions/32282/regex-testing) for regex creation tools, or [RegExp.info](http://regular-expressions.info/) for a nicer tutorial. – mario Apr 20 '12 at 00:50
  • Whole block is a single string, yes. –  Apr 20 '12 at 00:52

5 Answers5

2

I am not sure a simple Regex is the way to go here, especially considering the variable count of data for each record.

So, what about splitting the string up?

By splitting it at every line break followed by a "[" and splitting each of the results at every line break you could evaluate each and every first line of a result with a simple regex and easily add the numerical data, if there is any.

Regards STEFAN

Stefan Dochow
  • 1,454
  • 1
  • 10
  • 11
0

This works for me:

<?php

$str = '[9] 20:30:40 [SUCCESS] s-a24:1337
2
8.87
4038047
35320
4002727
[10] 20:30:40 [SUCCESS] s-d28:1337
2
2.64
4038047
37363
4000684
[11] 20:30:40 [SUCCESS] s-b29:1337
2
0.56
4038047
33066
4004981
[66] 20:30:42 [FAILURE] s-b25:1337 Timed out, Killed by signal 9
2
1.16
4038047
35274
[67] 20:30:42 [FAILURE] s-b30:1337 Timed out, Killed by signal 9';

preg_match_all("/^\[.*?\[(SUCCESS|FAILURE)\]\s(s\-\w\d{2}):1337.*?\n((.*\n){5})/m", $str, $matches, PREG_SET_ORDER);
//print_r($matches);
foreach ($matches as $match)
{
    echo $match[1] . "<br>\n";
    echo $match[2] . "<br>\n";
    echo $match[3] . "<br>\n";
}
?>
John Conde
  • 217,595
  • 99
  • 455
  • 496
  • should be {0,5} instead of {5} near the end there, and it still misses the final FAILURE case where no numbers follow. – Chris Apr 20 '12 at 01:47
0

(\[\d*\].*\[(SUCCESS|FAILURE)\]\s(s-.{3}).*(\r[\d\.]+){0,5})

http://regexr.com?30n45

This regex should work.

Jack
  • 5,680
  • 10
  • 49
  • 74
0

Quick and dirty, but it was fun to try:

$success_pattern = '/\[(SUCCESS|FAILURE)\]/';
preg_match_all($success_pattern, $subject, $success_matches);

$descriptor_pattern = '/\[(SUCCESS|FAILURE)\]\s(.+?):/';
preg_match_all($descriptor_pattern, $subject, $descriptor_matches);

$numbers_pattern = '/\[.*?\n((\d+\.{0,1}\d*\n)+)/';
preg_match_all($numbers_pattern, $subject, $numbers_matches);

$output = array();
for($x = 0; $x < count($success_matches[0]); $x++) {
    $output[] = array(
        'success' => $success_matches[1][$x],
        'descriptor' => $descriptor_matches[2][$x],
        'numbers' => explode("\n", trim($numbers_matches[1][$x]))
    );
}
Chris
  • 6,805
  • 3
  • 35
  • 50
0

How about:

$string = '[9] 20:30:40 [SUCCESS] s-a24:1337
2
8.87
4038047
35320
4002727
[10] 20:30:40 [SUCCESS] s-d28:1337
2
2.64
4038047
37363
4000684
[11] 20:30:40 [SUCCESS] s-b29:1337
2
0.56
4038047
33066
4004981
[66] 20:30:42 [FAILURE] s-b25:1337 Timed out, Killed by signal 9
2
1.16
4038047
35274
[67] 20:30:42 [FAILURE] s-b30:1337 Timed out, Killed by signal 9
';

preg_match_all("/\[.*?\[(SUCCESS|FAILURE)\]\s+([^:]+):[^\n]+\n(?:([^[]+?)\n)?(?:([^[]+?)\n)?(?:([^[]+?)\n)?(?:([^[]+?)\n)?(?:([^[]+?)\n)?/m", $string, $matches, PREG_SET_ORDER);
print_r($matches);

output:

Array
(
    [0] => Array
        (
            [0] => [9] 20:30:40 [SUCCESS] s-a24:1337
2
8.87
4038047
35320
4002727

            [1] => SUCCESS
            [2] => s-a24
            [3] => 2
            [4] => 8.87
            [5] => 4038047
            [6] => 35320
            [7] => 4002727
        )

    [1] => Array
        (
            [0] => [10] 20:30:40 [SUCCESS] s-d28:1337
2
2.64
4038047
37363
4000684

            [1] => SUCCESS
            [2] => s-d28
            [3] => 2
            [4] => 2.64
            [5] => 4038047
            [6] => 37363
            [7] => 4000684
        )

    [2] => Array
        (
            [0] => [11] 20:30:40 [SUCCESS] s-b29:1337
2
0.56
4038047
33066
4004981

            [1] => SUCCESS
            [2] => s-b29
            [3] => 2
            [4] => 0.56
            [5] => 4038047
            [6] => 33066
            [7] => 4004981
        )

    [3] => Array
        (
            [0] => [66] 20:30:42 [FAILURE] s-b25:1337 Timed out, Killed by signal 9
2
1.16
4038047
35274

            [1] => FAILURE
            [2] => s-b25
            [3] => 2
            [4] => 1.16
            [5] => 4038047
            [6] => 35274
        )

    [4] => Array
        (
            [0] => [67] 20:30:42 [FAILURE] s-b30:1337 Timed out, Killed by signal 9

            [1] => FAILURE
            [2] => s-b30
        )

)
Toto
  • 89,455
  • 62
  • 89
  • 125
  • This almost works. However the last part, that matches the 5 rows of numbers, only has the last row in the array. First 4 are not. I ran your exact example, and got different results. WHat version of PHP are you running? Im running 5.3.10 –  Apr 20 '12 at 19:21
  • @k1lljoy: Sorry, I've copy/paste wrong code. See my edit: change `(?:([^[]+?)\n){0,5}` with `(?:([^[]+?)\n)?(?:([^[]+?)\n)?(?:([^[]+?)\n)?(?:([^[]+?)\n)?(?:([^[]+?)\n)?` – Toto Apr 21 '12 at 07:14