\n at end of embedded string causes regex to fail to match

Viewed 47

Using the below regex's I'm attempting to extract a string value that is contained in double quotes and convert the matches values into a Map. This works as expected for the string "e,r,t,\"$0 = 1\n$1 = 2\n$5 = 6\",a,b,c,d"; but when I add a \n to at end of embedded string : "e,r,t,\"$0 = 1\n$1 = 2\n$5 = 6\n\",a,b,c,d"; the map is not populated.

src :

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ReadLine {

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

        final String st = "e,r,t,\"$0 = 1\n$1 = 2\n$5 = 6\n\",a,b,c,d";

        final Pattern quotesPattern = Pattern.compile("\"(.*?)\"", Pattern.DOTALL);
        final Matcher quotesMatcher = quotesPattern.matcher(st);
        quotesMatcher.find();
        String mv = quotesMatcher.group(0).replace("\n", ", ");
        System.out.println("mv : " + mv);

        final Map<String, String> mappedValues = new HashMap<String, String>();

        final Pattern find = Pattern.compile("(\" *\\$\\p{Alnum}+ *= *\\p{Alnum}+ *(?:, *\\$\\p{Alnum}+ *= *\\p{Alnum}+ *)*\")");
        final Pattern extract = Pattern.compile("\\$(\\p{Alnum}+) *= *(\\p{Alnum}+)");

        final Matcher matcher = find.matcher(mv);
        while (matcher.find()) {
            final Matcher extractor2 = extract.matcher(matcher.group(0));
            while (extractor2.find())
                System.out.println(extractor2.group(1) +"->"+extractor2.group(2));
        }
    }

}

which prints:

mv : "$0 = 1, $1 = 2, $5 = 6, "

The regex is not matched.

If I use instead :

final String st = "e,r,t,\"$0 = 1\n$1 = 2\n$5 = 6\",a,b,c,d";

prints :

mv : "$0 = 1, $1 = 2, $5 = 6"
0->1
1->2
5->6

So the omission of \n allows the regex to match.

I expect

0->1
1->2
5->6

to matched regardless of if \n occurs at end of embedded string or not.

I don't like the fact of using String mv = quotesMatcher.group(0).replace("\n", ", "); and there is likely a cleaner way of parsing these values but how to edit so that if \n occurs at end of embedded string the values are matched ?

1 Answers

Change your find regex Pattern from

(\" *\\$\\p{Alnum}+ *= *\\p{Alnum}+ *(?:, *\\$\\p{Alnum}+ *= *\\p{Alnum}+ *)*\")

to

\" *\\$\\p{Alnum}+ *= *\\p{Alnum}+ *(?:, *\\$\\p{Alnum}+ *= *\\p{Alnum}+ *)*(, )?\"

The brackets () around the regex are not required and, hence, removed.

(, )? at the tail end instructs the matcher to match even if the mapped values string ends with a , and the ? after it tells the matcher that its presence is optional.

Related