Java regex lazy operator not so lazy?
I have Java class that have to fetch the content of an URL online (returning an XML), and apply a regexp over it (the behaviour is defined by third-party files, I so cannot use DOM or SAX to parse the response). Here is the code :
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegExpTest {
public static void main(String[] args) {
try {
StringBuffer buffer = new StringBuffer();
URL url = new URL("http://api.themoviedb.org/2.1/Movie.search/en/xml/57983e31fb435df4df77afb854740ea9/Inglourious+Bastards");
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.connect();
InputStream input = conn.getInputStream();
for(int c = input.read(); c != -1; c = input.read())
buffer.append((char)c);
Pattern pattern = Pattern.compile("<movie>.*?<name>([^<]*)</name>.*?<id>([^<]*)</id>.*?</movie>", Pattern.DOTALL);
Matcher matcher = pattern.matcher(buffer);
for(int i = 1; i < (matcher.groupCount() + 1); i++) {
matcher.find();
开发者_开发百科 String toReplace = matcher.group(i);
System.out.println(toReplace);
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}
Its output is for this sample "Inglourious Basterds" and then "22311", which is the content of the name tag in the first movie tag, and the content of the id tag in the second movie tag. However, the lazy operator should guarantee that it is only the items in the first movie tag that are retrieved.
Moreover, the following code in python, which basically does exactly the same, works in the expected way.
import re
import urllib
url = urllib.urlopen("http://api.themoviedb.org/2.1/Movie.search/en/xml/"
"57983e31fb435df4df77afb854740ea9/Inglourious+Bastards")
m = re.search("<movie>.*?<name>([^<]*)</name>.*?<id>([^<]*)</id>.*?</movie>",
url.read(), re.DOTALL)
print m.group(1), m.group(2)
Any idea on what is wrong with my code ?
Thanks
There are two capturing groups in the regex, so find()
gets called twice. You need to call find()
(and check the result) before you start looking at the match info:
while (matcher.find()) {
for(int i = 1; i < (matcher.groupCount() + 1); i++) {
String toReplace = matcher.group(i);
System.out.println(toReplace);
}
}
精彩评论