Java Regex Matcher Question - java

How do I match an URL string like this:
img src = "https://stackoverflow.com/a/b/c/d/someimage.jpg"
where only the domain name and the file extension (jpg) is fixed while others are variables?
The following code does not seem working:
Pattern p = Pattern.compile("<img src=\"http://stachoverflow.com/.*jpg");
// Create a matcher with an input string
Matcher m = p.matcher(url);
while (m.find()) {
String s = m.toString();
}

There were a couple of issues with the regex matching the sample string you gave. You were close, though. Here's your code fixed to make it work:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class TCPChat {
static public void main(String[] args) {
String url = "<img src=\"http://stackoverflow.com/a/b/c/d/someimage.jpg\">";
Pattern p = Pattern.compile("<img src=\"http://stackoverflow.com/.*jpg\">");
// Create a matcher with an input string
Matcher m = p.matcher(url);
while (m.find()) {
String s = m.toString();
System.out.println(s);
}
}
}

First, I would use the group() method to retrieve the matched text, not toString(). But it's probably just the URL part you want, so I would use parentheses to capture that part and call group(1) retrieve it.
Second, I wouldn't assume src was the first attribute in the <img> tag. On SO, for example, it's usually preceded by a class attribute. You want to add something to match intervening attributes, but make sure it can't match beyond the end of the tag. [^<>]+ will probably suffice.
Third, I would use something more restrictive than .* to match the unknown part to the path. There's always a chance that you'll find two URLs on one line, like this:
<img src="http://so.com/foo.jpg"> blah <img src="http://so.com/bar.jpg">
In that case, the .* in your regex would bridge the gap, giving you one match where you wanted two. Again, [^<>]* will probably be restrictive enough.
There are several other potential problems as well. Are attribute values always enclosed in double-quotes, or could they be single-quoted, or not quoted at all? Will there be whitespace around the =? Are element and attribute names always lowercase?
...and I could go on. As has been pointed out many, many times here on SO, regexes are not really the right tool for working with HTML. They can usually handle simple tasks like this one, but it's essential that you understand their limitations.
Here's my revised version of your regex (as a Java string literal):
"(?i)<img[^<>]+src\\s*=\\s*[\"']?(http://stackoverflow\\.com/[^<>]+\\.jpg)"

Related

Java regex only finding one match

I'm using the following regex:
(?<=<((Pswrd>)|([^/]{1,2147483646}?:Pswrd>)))((?s).+?)(?=</(\\1))
And I have the following text to match:
<abc:Pswrd>PASSWORD_ONE</abc:Pswrd>
<Pswrd>PASSWORD_TWO</Pswrd>
I need to match the context of both XML tags but is only working for the second one.
The output is:
PASSWORD_TWO
And it should be:
PASSWORD_ONE
PASSWORD_TWO
It seems the OR is not working for some reason?
String message = " <abc:Pswrd>PASSWORD_ONE</abc:Pswrd>\n" +
" <Pswrd>PASSWORD_TWO</Pswrd>";
String regex = "(?<=<((Pswrd>)|([^/]{1,2147483646}?:Pswrd>)))((?s).+?)(?=</(\\1))";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(message);
while (matcher.find()) {
String group = matcher.group();
System.out.println(group);
}
Thanks
Update: It needs to be the matching group 0.
So in order to either match <Pswd> or <abc:Pswd> or <something:Pswd>, the RegEx would need to look something like <\w*:*Pswrd>. The problem however is that the look behind does not like non-fixed width quantifiers, so you can't create a look behind that caters for a "dynamic"
Instead I would suggest just go for something simple, such as :
(?<=Pswrd>)(.*)(?=<\/)
Essentially here you just look for the last bit of the opening tag (namely "Pswrd>") then you match any thing between that and the closing portion of the tag.

Regex matches in Ruby, but not in Java?

Just in an attempt to get more experience with regex (while also making life easier at work) I was trying to parse some filenames in Java.
My string is this: /home/user/example/Results/ExampleFilePrefix_20140324-0500_OptionalTextThatMightContainNumbers123.csv
basically the filename will always start with ExampleFilePrefix_ followed by the timestamp, and sometimes ends with OptionalTextThatMightContainNumbers123 just depending on how the file was generated. The relevant information I want is the timestamp followed by the optional text if it exists.
I was messing around with various regular expressions and while I can get them all to work with a Ruby regex parser I can't get any of them to work in Java. I didn't keep track of them as I went, but this is my most recent attempt:
_(\w+-\w+)
Which works as expected in Ruby: http://rubular.com/r/K2BiboURRo, but doesn't even come close to matching in Java: http://fiddle.re/c7m04
I don't think it's a problem the code I've written due to the fact the online parser doesn't match, but I'll paste it here to be sure.
private String extractFileName(String filename) {
String resultNameBase = "RegexDidntMatch";
Pattern pattern = Pattern.compile("_(\\w+-\\w+)", Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(filename);
if (matcher.matches() && matcher.find()) {
resultNameBase = matcher.group(1);
}
return resultNameBase;
}
As always, thanks to all in advance
First of of its only matcher.find() And the catch the group 0 instead of 1.
if (matcher.find()) {
resultNameBase = matcher.group();
}
This part is problem:
if (matcher.matches() && matcher.find())
Matcher#matches() matches complete input string with your regex.
Replace that with:
if (matcher.find())

Use RegEx in Java to extract parameters in between parentheses

I'm writing a utility to extract the names of header files from JSPs. I have no problem reading the JSPs line by line and finding the lines I need. I am having a problem extracting the specific text needed using regex. After looking at many similar questions I'm hitting a brick wall.
An example of the String I'll be matching from within is:
<jsp:include page="<%=Pages.getString(\"MY_HEADER\")%>" flush="true"></jsp:include>
All I need is MY_HEADER for this example. Any time I have this tag:
<%=Pages.getString
I need what comes between this:
<%=Pages.getString(\" and this: )%>
Here is what I have currently (which is not working, I might add) :
String currentLine;
while ((currentLine = fileReader.readLine()) != null)
{
Pattern pattern = Pattern.compile("<%=Pages\\.getString\\(\\\\\"([^\\\\]*)");
Matcher matcher = pattern.matcher(currentLine);
while(matcher.find()) {
System.out.println(matcher.group(1).toString());
}}
I need to be able to use the Java RegEx API and regex to extract those header names.
Any help on this issue is greatly appreciated. Thanks!
EDIT:
Resolved this issue, thankfully. The tricky part was, after being given the right regex, it had to be taken into account that the String I was feeding to the regex was always going to have two " / " characters ( (/"MY_HEADER"/) ) that needed to be escaped in the pattern.
Here is what worked (thanks to the help ;-)):
Pattern pattern = Pattern.compile("<%=Pages\\.getString\\(\\\\\"([^\\\\\"]*)");
This should do the trick:
<%=Pages\\.getString\\(\\\\\"([^\\\\]*)
Yeah that's a scary number of back slashes. matcher.group(1) should return MY_HEADER. It starts at the \" and matches everything until the next \ (which I assume here will be at \")%>.)
Of course, if your target text contains a backslash (\), this will not work. But you didn't give an indication that you'd ever be looking for something like <%=Pages.getString(\"Fun!\Yay!\")%> -- where this regex would only return Fun! and ignore the rest.
EDIT
The reason your test case was failing is because you were using this test string:
String currentLine = "<%=Pages.getString(\"MY_HEADER\")%>";
This is the equivalent of reading it in from a file and seeing:
<%=Pages.getString("MY_HEADER")%>
Note the lack of any \. You need to use this instead:
String sCurrentLine = "<%=Pages.getString(\\\"MY_HEADER\\\")%>";
Which is the equivalent of what you want.
This is test code that works:
String currentLine = "<%=Pages.getString(\\\"MY_HEADER\\\")%>";
Pattern pattern = Pattern.compile("<%=Pages\\.getString\\(\\\\\"([^\\\\]*)");
Matcher matcher = pattern.matcher(currentLine);
while(matcher.find()) {
System.out.println(matcher.group(1).toString());
}

How to match a word(String) in URL

This website contains different Url, But i want my application should vist urls only which contains specific keyword like "drugs" like
if urls are
http://website.com/countryname/drug/info/A
http://website.com/countryname/Browse/Alphabet/D?cat=company
it should visit first URL.so how to match a specific keyword drug in url.I know it can be done using regexp also,but have but i am new to it
I am using Java here
You can check if string contains a word with method contains().
if(myString.contains("drugs"))
If you need only URLs containing /drug/ try to do something like this:
Pattern p = Pattern.compile("/drug(/|$)");
Matcher m = p.matcher(myURLString);
if(m.find())
{
something_to_do
}
(/|$) means that after /drug can be only a slash ( / ) or nothing at all (dollar means end of the line).So this regex will find all if your string is like .../drug/... or .../drug
Use split() as such:
final String[] words = input.replaceFirst("https?://", "").split("/+");
for (final String word: words)
if ("whatyouwant".equals(word))
//do what is necessary since the word matches
If your code is called very often, you may want to make Patterns out of https?:// and /+ and use Matchers.

Simple regex extract folders

What would be the most efficient way to cover all cases for a retrieve of folder1/folder22
from:
http://localhost:8080/folder1/folder22/file.jpg
or
http://domain.com/folder1/folder22/file.jpg
or
http://127.0.0.0.1:8080/folder1/folder22/file.jpg
so there may be one or more folders/sub-folders. Basically I would like to strip the domain name and port if available and the file name at the end.
Thank for your time.
What about the URL class and getPath()?
Maybe it's not the most efficient way, but one of the simplest I think:
String[] urls = {
"http://localhost:8080/folder1/folder22/file.jpg",
"http://domain.com/folder1/folder22/file.jpg",
"http://127.0.0.0.1:8080/folder1/folder22/file.jpg" };
for (String url : urls)
System.out.println(new File(new URL(url).getPath()).getParent());
You should probably use Java's URL parser for this, but if it has to be a regex:
\b(?=/).*(?=/[^/\r\n]*)
will match /folder1/folder22 in all your examples.
try {
Pattern regex = Pattern.compile("\\b(?=/).*(?=/[^/\r\n]*)");
Matcher regexMatcher = regex.matcher(subjectString);
if (regexMatcher.find()) {
ResultString = regexMatcher.group();
}
Explanation:
\b: Assert position at a word boundary (this will work before a single slash, but not between slashes or after a :)
(?=/): Assert that the next character is a slash.
.*: Match anything until...
(?=/[^/\r\n]*): ...exactly one last / (and anything else except slashes or newlines) follows.
^.+/([^/]+/[^/]+)/[^/]+$
The best way to get the last two directories from a url is the following:
preg_match("/\/([^\/]+\/){2}[^\/]+$/", $path, $matches);
If matched, And $matches[1] will always contain what you want, no matter filename of full url.

Categories