Hey Everyone... Not quite sure how it works on these forums as this is my first post, but I am looking to separate elements of lines printed to a text file in real-time for a log parser.

An example of the text output is:
[CHAT WINDOW TEXT] [Sun Nov 29 11:34:38] Guardian of Water killed Kyton's Rebuke [BH]

I would like to separate the two names (Guardian of Water and Kyton's Rebuke [BH]) and use the word killed as a keyword in an if...else... statement. Keep in mind however that the names can be extremely long or extremely short - there is no limit to the number of words in a name.

Also, for a line such as:
[CHAT WINDOW TEXT] [Sun Nov 29 11:34:10] Attack Of Opportunity : Soul Devourer attacks Kyton's Rebuke [BH] : *miss* : (13 + 113 = 126)
I would like to parse out the names (Soul Devourer and Kyton's Rebuke[BH]), the miss, and the 113.

Any ideas would be greatly appreciated, as i am a relatively new java programmer.

TJ

Recommended Answers

All 20 Replies

Thanks for the response masijade. I am still confused however how i would format a regex for a line like this:
[CHAT WINDOW TEXT] [Sun Nov 29 11:34:10] Attack Of Opportunity : Soul Devourer attacks Kyton's Rebuke [BH] : *miss* : (13 + 113 = 126)
I this line i would need the Attack of Opportunity, both names, the miss, and the 113 recorded somewhere. i can probably use colons to separate some pieces, but i am not sure as to how i can separate the 113 by looking for the + and = signs in that expression. and sometimes there will be more than one of those expressions on the end of the line, but the second is nothing to worry about. I have come up with a list of strings that i need to check for, and could be used to help separate names and other changing parts of the expression.

// REGEX TERMS
    
    public static final String MISS = ": *miss* :";
    public static final String ATTACKS = " attacks ";
    public static final String AOO = "Attack Of Opportunity :";
    public static final String HIT = "*hit*";
    public static final String CRIT = ": *critical hit* :";
    public static final String THREAT = ": Threat Roll:";
    public static final String CONCEAL = ": *target concealed ";
    public static final String REFSAVE = ": Reflex Save vs. ";
    public static final String WILLSAVE = ": Will Save vs. ";
    public static final String FORTSAVE = ": Fortitude Save vs. ";
    public static final String KILLED = " killed ";

But again, i am not sure how i would go about using terms like these to create regex statements. If someone wouldn't mind giving me an example and explaining how they created it (in newbie java terms) so i could try to create the rest, it would be greatly appreciated.

TJ

^.*\\]\\s+Attack Of Opportunity\\s+:\\s+(.+)\\s+attacks\\s+(.+)\\s+\\[.*\\*([\\w]+)\\*.*\\+\\s+(\\d+)\\s+=.*$

See the tutorials, and then you tell me how you think it works. And this is a simple "brute force" method.

^.*\\]\\s+Attack Of Opportunity\\s+:\\s+(.+)\\s+attacks\\s+(.+)\\s+\\[.*\\*([\\w]+)\\*.*\\+\\s+(\\d+)\\s+=.*$

so the ^.*\\] takes all of the text to the left of the last bracket and states that as part of a regex. after that, the \\s defines a space, and then the phrase Attack Of Opportunity is checked for. then, it checks for another space with \\s, then a colon, then another space, then the name with (.+), then another space, then the phrase attacks, and then another space. after that, it checks for a second name, then a space, and then after that i *believe* that it checks for an "*" then a word, and then another "*" followed by a space, then a series of digits followed by an "=" and a string of length 0 or more. then the strign terminates. I think this is what you were asking for, and i think i could reproduce the beginning but the end would be extremely confusing for me to create.

TJ

^.*\\]\\s+Attack Of Opportunity\\s+:\\s+(.+)\\s+attacks\\s+(.+)\\s+\\[.*\\*([\\w]+)\\*.*\\+\\s+(\\d+)\\s+=.*$

so the ^.*\\] takes all of the text to the left of the last bracket and states that as part of a regex. after that, the \\s defines a space, and then the phrase Attack Of Opportunity is checked for. then, it checks for another space with \\s, then a colon, then another space, then the name with (.+), then another space, then the phrase attacks, and then another space. after that, it checks for a second name, then a space, and then after that i *believe* that it checks for an "*" then a word, and then another "*" followed by a space, then a series of digits followed by an "=" and a string of length 0 or more. then the strign terminates. I think this is what you were asking for, and i think i could reproduce the beginning but the end would be extremely confusing for me to create.

TJ

The bold part is wrong. followed by "anything" then a space, a plus, a space, numbers, a space, "=", and "rest of string". The four groups of parens are save blocks, so there is your saved name1, name2, "miss", and "113".

ah okay thanks you very much. and how would i save them to individual variables?

Im trying to make a log parser that is going to have a lot of lines printed to it every second at times and they are going to vary type so i am trying to get the regex statements down as i believe this is the most efficient way to parse the files.

TJ

See the second and third links above. The first is general regex, not just Java.

So correct me if i'm wrong (which i believe i am), but would i save the first regex by referencing it as /1? as in

partyMember1 = /1;

I dont think this is correct, but one of the sites says

For example, the expression (\d\d) defines one capturing group matching two digits in a row, which can be recalled later in the expression via the backreference \1.

which leads me to believe that the way i have above is how one would go about doing it...

TJ

What do the Pattern and Matcher API docs say about "capturing groups" and what does the Java regex tutorial show about it?

Write a small test program with that String hard-coded in and try out varying patterns and varying ways of using Pattern and Matcher. Once you have done that, and it is still working as you think it should post that code here and I will help you get it right, but I have pointed you to exactly what you need (which at this point is the second and third links) you just need try it out.

Okay, so i came up with:

public class TestPattern {

    public static String aosRegex = "^.*\\]\\s+Attack Of Opportunity\\s+:\\s+(.+)\\s+attacks\\s+(.+)\\s+\\[.*\\*([\\w]+)\\*.*\\+\\s+(\\d+)\\s+=.*$";
    public static String testInput = "[CHAT WINDOW TEXT] [Sun Nov 29 11:34:10] Attack Of Opportunity : Soul Devourer attacks Kyton's Rebuke [BH] : *miss* : (13 + 113 = 126)";

    public static Pattern aosPattern = Pattern.compile(aosRegex);
    public static Matcher aosMatcher = aosPattern.matcher(testInput);

    

    public static void main(String[] args) {
        boolean matches = aosMatcher.matches();
        System.out.println(matches);
        String group = aosMatcher.group(1);
        System.out.println(group);

    }
}

and it returns true when it is run. do you see any errors in that?

TJ

okay well its no longer letting me edit my post, so i have to create a new one. I have succeeded in storing groups, etc, but i have found that the regex you gave me does not register the [BH] at the end of the players name. Run the code and i will show you what i mean.

public class TestPattern { 

    public static String aosRegex = "^.*\\]\\s+(Attack Of Opportunity)\\s+:\\s+(.+)\\s+attacks\\s+(.+)\\s+\\[.*\\*([\\w]+)\\*.*\\+\\s+(\\d+)\\s+=.*$";
    public static String testInput = "[CHAT WINDOW TEXT] [Sun Nov 29 11:34:10] Attack Of Opportunity : Soul Devourer attacks Kyton's Rebuke [BH] : *miss* : (13 + 113 = 126)";

    public static Pattern aosPattern = Pattern.compile(aosRegex);
    public static Matcher aosMatcher = aosPattern.matcher(testInput);
    public static String AOO = "Attack Of Opportunity";
    

    public static void main(String[] args) {
        boolean matches = aosMatcher.matches();
        System.out.println(matches);
        String group2 = aosMatcher.group(2);
        String enemy = group2;
        String group3 = aosMatcher.group(3);
        String player1 = group3;
        String group1 = aosMatcher.group(1);
        if (group1.equalsIgnoreCase(AOO)) {
            System.out.println("Attack of Opportunity registered on "+ enemy + " by "+ player1+".");
        }
        else System.out.println("Not an Attack of Opportunity");
    }
}

TJ

again, im just over the 30 minute limit... but i got the [BH] to appear by changing the regex to

public class TestPattern {

    public static String aosRegex = "^.*\\]\\s+(Attack Of Opportunity)\\s+:\\s+(.+)\\s+attacks\\s+(.+\\s+\\[.*)\\s+:\\s\\*([\\w]+)\\*.*\\+\\s+(\\d+)\\s+=.*$";
    public static String testInput = "[CHAT WINDOW TEXT] [Sun Nov 29 11:34:10] Attack Of Opportunity : Soul Devourer attacks Kyton's Rebuke [BH] : *miss* : (13 + 113 = 126)";

    public static Pattern aosPattern = Pattern.compile(aosRegex);
    public static Matcher aosMatcher = aosPattern.matcher(testInput);
    public static String AOO = "Attack Of Opportunity"; 

    public static void main(String[] args) {
        boolean matches = aosMatcher.matches();
        System.out.println(matches);
        String group2 = aosMatcher.group(2);
        String enemy = group2;
        String group3 = aosMatcher.group(3);
        String player1 = group3;
        String group1 = aosMatcher.group(1);
        if (group1.equalsIgnoreCase(AOO)) {
            System.out.println("Attack of Opportunity registered as a " + aosMatcher.group(4) +" on "+ enemy + " by "+ player1+".");
        }
        else System.out.println("Not an Attack of Opportunity");
    }
}

and now the output is as desired....

If i were to try to create regex statements for the rest of the statements i need them for would you mind checking them for me?

TJ

So my current code is:

import java.util.regex.*;
import javax.swing.*;
import java.io.*;
import java.util.*;

/**
 * @author tim_costa
 * @created on Dec 1, 2009 at 6:55:46 PM
 * original package is Tester 
Expecting a string, date or number here, Expression project is instead a freemarker.template.SimpleHash
 */
public class TestPattern implements variables{

    public static String damInput = "[CHAT WINDOW TEXT] [Sun Nov 29 11:34:09] Anymental damages Kyton's Rebuke [BH]: 24 (24 Electrical)";
    public static String damRegex = "^.*\\]\\s+(.+)\\s+damages\\s+(.+)+:\\s(\\d+)+(.*)$";

    public static String aooRegex = "^.*\\]\\s+(Attack Of Opportunity)\\s+:\\s+(.+)\\s+attacks\\s+(.+)\\s+:\\s\\*([\\w]+)\\*.*\\+\\s+(\\d+)\\s+=.*$";
    public static String testInput = "[CHAT WINDOW TEXT] [Sun Nov 29 11:34:10] Attack Of Opportunity : Soul Devourer attacks Kyton's Rebuke [BH] : *miss* : (13 + 113 = 126)";

    public static Pattern aooPattern = Pattern.compile(aooRegex);
    public static Matcher aooMatcher = aooPattern.matcher(testInput);
    public static Pattern damPattern = Pattern.compile(damRegex);
    public static Matcher damMatcher = damPattern.matcher(damInput);

    public static void main(String[] args) throws FileNotFoundException {

        for (int i = 0; i<=100; i++) {
            //File current = new File("testlog.txt");
            damMatch();
            aooMatch();
            System.out.println(i);
            System.out.println();
        }
        
        
        
    }

    public static void damMatch() {
        boolean matchesDamage = damMatcher.matches();              //TRY MOVING THIS TO THE MAIN METHOD. PROGRAM MOVES MUCH FASTER
        if (matchesDamage == true) {
            String attacker = damMatcher.group(1);
            String attackee = damMatcher.group(2);
            String totalDam = damMatcher.group(3);
            String damBreakdown = damMatcher.group(4);
            System.out.println(attacker + " damages " + attackee + " " + totalDam + " total.");
            System.out.println("\t The damage breakdown is:"+ damBreakdown + ".");
        }
    }

    public static void aooMatch() {
        boolean matches = aooMatcher.matches();                                     //HAS NO EFFECT ON PROGRAM SPEED
        if ((aooMatcher.group(1)).equalsIgnoreCase(AOO) && matches == true) {
            String attackee = aooMatcher.group(2);
            String attacker = aooMatcher.group(3);
            System.out.println("Attack of Opportunity registered as a " + aooMatcher.group(4) +" on "+ attackee + " by "+ attacker+".");
        }
        else System.out.println("Not an Attack of Opportunity");
    }
}

I have added two comments, because i have noticed the speed of the program varying greatly if i move one of my matching statements, and at the speed it moves at where the statement is (and should be) is not acceptable.... anyone have any ideas?

TJ

I have used Mid,InStr and other methods to get a substring of a string from one text file and copied the required string to another text file. While I get the correct string, vbscript however generates a BLANK SPACE after evry character in the output string.

I tried to use the Replace function inorder to replace the " " with ""... but the function does not detect any blank spaces at all to replace.

Instead of copying to another file, I even tried to replace the undesired part of the string with a " " and get only the required part ... but then again it gives the same problem[ a BLANK SPACE after evry character]

How do I resolve this issue.

Please help.

A VB Complaint

This is a Java forum. Go to the VB forum and post a new question there (i.e. start a new thread, do not hijack someone else's).

I saw this link in the similar threads on my original thread.. so I thot I could use it. Wasn't trying to hijack.. just finding a common audience since Daniweb has no seperate section for vbScript

Maybe not, but VB is much closer to it than Java.

no no vbscript is totally totally different from vb

Still closer than Java though. Maybe try a JavaScript forum? Or even better this

thankx. good idea. i'l surely try that.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.