2

Can anyone help where I am doing wrong?

My sample text :

{[|Name:A|Class:1|Sex:Male|][|Name:B|Class:2|Sex:Female|][|Name:C|Class:3|Sex:Male|]}

Expected output:

|Name:A|Class:1|Sex:Male|
Name:A
Class:1
Sex:Male
|Name:B|Class:2|Sex:Female|
Name:B
Class:2
Sex:Female
|Name:C|Class:3|Sex:Male|
Name:C
Class:3
Sex:Male

Current output :

|Name:A|Class:1|Sex:Male|
Name:A
Sex:Male
|Name:B|Class:2|Sex:Female|
Name:B
Sex:Female
|Name:C|Class:3|Sex:Male|
Name:C
Sex:Male

My program:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Regex {

    public static void main(String[] args) {

        String example = "{[|Name:A|Class:1|Sex:Male|][|Name:B|Class:2|Sex:Female|][|Name:C|Class:3|Sex:Male|]}";

        Pattern curlyBraces = Pattern.compile("\\[(.*?)\\]");

        Matcher m = curlyBraces.matcher(example);
        while (m.find()) {
            System.out.println(m.group(1));
            String element = m.group(1);
            Pattern pipe = Pattern.compile("\\|(.*?)\\|");
            Matcher mPipe = pipe.matcher(element);
            while (mPipe.find()) {
                System.out.println(mPipe.group(1));
            }
        }
    }
}
1
  • Given that you program prints using println, it's extremely unlikely that your output is a single line of text, like you showed, so please format entire question correctly, so we know that you want and what you're actually getting right now. Commented Feb 4, 2016 at 7:24

2 Answers 2

1

Your problem is that "\\|(.*?)\\|" will only match |Name:A| and |Sex:Male| in the line

|Name:A|Class:1|Sex:Male|

because the regex consumes the characters it's matching, and the | between Name:A and Class:1 therefore can only be matched once.

Use lookaround assertions to get around that - they don't consume the text they match:

        Pattern pipe = Pattern.compile("(?<=\\|).*?(?=\\|)");
        Matcher mPipe = pipe.matcher(element);
        while (mPipe.find()) {
            System.out.println(mPipe.group(0));
        }

Another possibility, if you're not expecting empty values, would be to match all "non-pipes" characters:

        Pattern pipe = Pattern.compile("[^|]+");
        Matcher mPipe = pipe.matcher(element);
        while (mPipe.find()) {
            System.out.println(mPipe.group(0));
        }
Sign up to request clarification or add additional context in comments.

Comments

0

Like Tim Pietzcker already discribed, the | gets conumed by the regex and then it can't find the Class:1.

But you don't need the second regex. Instead of the regex you could use a normal string.split("|"). Should work in your case and is probably faster:

String element = m.group(1);
String[] splitString = element.split("\\|"); // splitString = ["Name:A", "Class:1", "Sex:Male"]

To avoid empty strings in splitString you would have to change your first regex Pattern to "\\[\\|(.*?)\\|\\]".

4 Comments

That gives you ["", "Name:A", "Class:1", "Sex:Male"] though - only trailing empty splits are removed by default.
You're right, though you could adjust the first Pattern to "\\[\\|(.*?)\\|\\]" and then you wouldn't have the issue with the empty splits. I'll update the answer.
Java's String#split() treats its argument as a regex, so you still have to escape the pipe.
@AlanMoore Thanks, totally forgot that. Updated the answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.