Using multiple regex to find attributes in a text and grouping them

Viewed 60

I have a text file with a fake Person data (from anytexteditor.com website, USA region) but it's a ctrl+c ctrl+v text with a lot of \t \s \n.
Something like this:
Donald the Duck data (those wide spaces are \t):


HomePersonal Details:
Country USA Name    Donald The Duck III
Address 1313  Disneyland Dr City    Anaheim
State   California  Zip Code    92802
Gender  Male    Date Of Birth   13-04-1942
Phone Number    +1-222-333-4444 E-Mail  donald.duck@thisisntarealmail.com
Financial Details:
Bank Name   DisneyLand Bank Bank Code   123
IBAN    123456789   Account Number  987654321
Credit Card Type    Donald The Duck III Credit Card Number  1234 5678 9012 3456
Credit Card Expiry  99/99   Credit Card CVV2    123
...

Or regex101.com with Donald data

I was able to extract some of data I needed by reading the file one line at a time but the code started to get really long with multiples if statements.
So I've decided to use the whole text as a String and then a single regex to group the data.
Something like this:

//It won't look like this, it's just for testing

public class ExtractingPersonFromTextFile {

    public static void main(String[] args) {
        
        String name = null;
        String gender = null;
        String birth = null;
        
        String fileInput = "donald_duck_data.txt";

        try {
            String textFile = Files.readString(Paths.get(fileInput));
            
            Pattern pattern = Pattern.compile(???);
            Matcher matcher = pattern.matcher(textFile);
            
            if(matcher.find()) {
                name = matcher.group(1); //from "Country    USA Name    Donald The D'Duck III"
                gender = matcher.group(2); //from "Gender   Male    Date Of Birth   13-04-1942"
                birth = matcher.group(3); //from "Gender    Male    Date Of Birth   13-04-1942
                System.out.println(name+", "+gender+", "birth);

            } else {System.out.println("oh oh regex not found");}   
            
        } catch (IOException e) {System.out.println(e.getMessage());}
        
    }

}

These are the regex I was using to group Name, Gender and Date Of Birth separately:

name regex: (?:\tName\t([A-Za-z\s\.\']+)\n)
gender and birthday regex: (?:Gender\t([A-Za-z]+))(?:\tDate\sOf\sBirth\t([\d\-]+)\n)

And I was trying to combine both regex into a single one but I was unable to do it.
I thought it would be something like this (?:\tName\t([A-Za-z\s\.\']+)\n)(?=Gender... like find "Name", place into group1 and then look ahead for the "Gender" group2 but no...
I was reading some posts about it but most are reading from a single line or searching for a single regex inside a long text file. So maybe this is not the best approach and I should just finish the initial code I did reading one line at a time.

Sorry for the long post, but ever since I started learning Java this is the first thing I cannot figure it out by myself and I've tried to be clear. Thanks

1 Answers

You can set the Pattern.DOTALL flag to make . match newlines, as default it doesn't. Also you can refactor your regex to match any values between your groups:

(?:\tName\t([A-Za-z\s\.\']+)[\r\n|\n]).*(?:Gender\t([A-Za-z]+)).*(?:\tDate\sOf\sBirth\t([\d\-]+))

Can you please review the following implementation:

Pattern pattern = Pattern
    .compile("(?:\\tName\\t([A-Za-z\\s\\.\\']+)[\\r\\n|\\n]).*(?:Gender\\t([A-Za-z]+)).*(?:\\tDate\\sOf\\sBirth\\t([\\d\\-]+))", Pattern.DOTALL);
Matcher matcher = pattern.matcher(textFile);
if (matcher.find()) {
  String name = matcher.group(1);
  String gender = matcher.group(2);
  String birth =  matcher.group(3);
  log.debug("name: {}, gender: {}, birth: {}", name,gender,birth);
}

After that, you can get the necessary values from the groups, Please see the following resut: enter image description here

Related