preg_match prob

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
steveatk
Forum Newbie
Posts: 6
Joined: Sat Dec 27, 2003 9:52 am

preg_match prob

Post by steveatk »

I'm having an odd problem with some regex code I'm working on, this is almost an exact copy from another program I wrote that works perfectly.

However this piece of code will only display the first expression results, no matter which way round you place them, it will only display the first set of results.

Should I be resetting anything in between them? The count output from the first section is always correct, but it's always zero on the second and any other sections after that. I haven't done a great deal with regex before so maybe I'm missing something important here.

It's probably something simple but any help would be appreciated as it's driving me crazy now.

Code: Select all

$date = '<([A-Z]{1}[a-z]{2}) ([0-9]{1,2}), ([0-1]?[0-9]|[2][0-3]):([0-5][0-9]):([0-5][0-9])>  ';
$skill_hit = 'You hit the ([a-zA-Z ]+) with ([a-zA-Z ]+) for ([0-9\,]+) points of damage\.';
$skill_evade = 'You try to use ([a-zA-Z ]+) on the ([a-zA-Z ]+), but it evades\.';

print ('<b>-------- SKILL HITS --------------------------------------</b><br>');
preg_match_all('/'.$date.$skill_hit.'/', $content, $matches);
print ('count = '.count($matches[0]).'<br>');
for ($i=0; $i< count($matches[0]); $i++)
{
    $date = $matches[1][$i].' '.$matches[2][$i];
    $time = $matches[3][$i].':'.$matches[4][$i].':'.$matches[5][$i];
    $mob = $matches[6][$i];
    $skill = $matches[7][$i];
    $dmg = $matches[8][$i];
    print ('<b>'.$date.', '.$time.' -</b> You hit the '.$mob.' with '.$skill.' for '.$dmg.' points of damage.<br>');
}

print ('<b>-------- SKILL EVADES --------------------------------------</b><br>');
preg_match_all('/'.$date.$skill_evade.'/', $content, $matches);
print ('count = '.count($matches[0]).'<br>');
for ($i=0; $i< count($matches[0]); $i++)
{
    $date = $matches[1][$i].' '.$matches[2][$i];
    $time = $matches[3][$i].':'.$matches[4][$i].':'.$matches[5][$i];
    $skill = $matches[6][$i];
    $mob = $matches[7][$i];
    print ('<b>'.$date.', '.$time.' -</b> You tried to use '.$skill.' on the '.$mob.', but it evaded.<br>');
}
steveatk
Forum Newbie
Posts: 6
Joined: Sat Dec 27, 2003 9:52 am

Post by steveatk »

I've been playing with this all day and still can't make it perform more than one preg_match_all successfully :(

However as a break I'm trying to work something else out now which I would like some advice on (the initial is problem is still there too so help on that would also be appreciated)

I have a log with multiple lines similar to the following.

Code: Select all

$content .= '<Dec 28, 15:11:10>  You try to use Skill Name on the Mob Name, but it evades.';
$content .= '<Dec 28, 15:11:11>  You hit the Mob Name with Skill Name for 307 points of damage.';
$content .= '<Dec 28, 15:11:13>  You hit the Mob Name for 136 points of damage.';
$content .= '<Dec 28, 15:11:13>  You hit the Mob Name for 149 points of damage.';
$content .= '<Dec 28, 15:11:15>  You hit the Mob Name for 144 points of damage.';
The test data above works fine, and I can extract various pieces of useful info but I am stumped on one particular expression..

I need to be able to identify when a target has been hit by a skill, which is already done. The problem arises when I want to detect an auto attack only (ie. no skill usage) so I need to use the same expresion but with a modification that tells it to only match if a part of it is NOT found..

Code: Select all

$skill_hit = 'You hit the ([a-zA-Z ]+) with ([+a-zA-Z ]+) for ([+0-9\,]+)';
This works but is it possible to use this section "with ([+a-zA-Z ]+)" as a negative test so that it matches the line only if the 1st and 3rd conditions are true and the second is NOT true?

At the moment, when trying to extract auto attacks only, it works ok but when encountering a line with a skill usage, the first expression contains "Mob Name with SKill Name" which of course satisifes that expression condition. The problem is that Mob Names can be multiple part names with up to 5 or 6 parts which adds some complexity to performing a simple test.

I could just use the one test to find any line with an attack and then perform a string search on each match to locate the string "with" but I would rather have a regex to identify exactly what I need without having to fudge it.

I tried the following and a huge variation after spending most of the day reading articles on the subject but still no joy.

Code: Select all

$skill_hit = 'You hit the ([a-zA-Z ]+) (?!with ([+a-zA-Z ]+))for ([+0-9\,]+)';
Any help for either of the two problems in this thread would be greatly appreciated.
steveatk
Forum Newbie
Posts: 6
Joined: Sat Dec 27, 2003 9:52 am

Post by steveatk »

I am an idiot, I just realised, after 3 days of head scratching - that I have been overwriting my date regex with something else.

Anyway, does anyone know how to do the NOT test I want?

It works if the word before "with" is static, but it changes with each entry.

I need to extract Mob name and Damage but only if 'with Skill Name' are NOT in the text.

Using ([a-zA-Z ]+) (?!with) doesn't work but if I replace the first condition in the expression with a string that is in the text (ie. a real Mob name) then it does work.

Is it not possible to do this test when the preceding text is variable?
Post Reply