开发者

RegEx in Java: how to deal with newline

I am currently trying to learn how to use regular expressions so please bear with my simple question. For example, say I have an input file containing a bunch of links separated by a newline:

www.foo.com/Archives/monkeys.htm

Description of Monkey's website.

www.foo.com/Archives/pigs.txt

Description of Pig's website.

www.foo.com/Archives/kitty.txt

Description of Kitty's website开发者_开发技巧.

www.foo.com/Archives/apple.htm

Description of Apple's website.

If I wanted to get one website along with its description, this regex seems to work on a testing tool: .*www.*\\s.*Pig.*

However, when I try running it within my code it doesn't seem to work. Is this expression correct? I tried replacing "\s" with "\n" and it doesn't seem to work still.


The lines are probably separated by \r\n in your file. Both \r (carriage return) and \n (linefeed) are considered line-separator characters in Java regexes, and the . metacharacter won't match either of them. \s will match those characters, so it consumes the \r, but that leaves .* to match the \n, which fails. Your tester probably used just \n to separate the lines, which was consumed by \s.

If I'm right, changing the \s to \s+ or [\r\n]+ should get it to work. That's probably all you need to do in this case, but sometimes you have to match exactly one line separator, or at least keep track of how many you're matching. In that case you need a regex that matches exactly one of any of the three most common line separator types: \r\n (Windows/DOS), \n (Unix/Linus/OSX) and \r (older Macs). Either of these will do:

\r\n|[\r\n]

\r\n|\n|\r

Update: As of Java 8 we have another option, \R. It matches any line separator, including not just \r\n, but several others as defined by the Unicode standard. It's equivalent to this:

\r\n|[\n\x0B\x0C\r\u0085\u2028\u2029]

Here's how you might use it:

(?im)^.*www.*\R.*Pig.*$

The i option makes it case-insensitive, and the m puts it in multiline mode, allowing ^ and $ to match at line boundaries.


For future reference, one can also use the Pattern.DOTALL flag for "." to match even \r or \n.

Example:

Say the we are parsing a single string of http header lines like this (each line ended with \r\n)

HTTP/1.1 302 Found
Server: Apache-Coyote/1.1
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: SAMEORIGIN
Location: http://localhost:8080/blah.htm
Content-Length: 0

This pattern:

final static Pattern PATTERN_LOCATION = Pattern.compile(".*?Location\\: (.*?)\\r.*?", Pattern.DOTALL);

Can parse the location value using "matcher.group(1)".

The "." in the above pattern will match \r and \n, so the above pattern can actually parse the 'Location' from the http header lines, where there might be other headers before or after the target line (not that this is a recommended way to parse http headers).

Also, you can use "?s" inside the pattern to achieve the same effect.

If you are doing this, you might be better off using Matcher.find().


String str="I am  a   "+"\n  Man    of  Peace"+"\t"+"   .";

str=str.replaceAll("[\\s|\\t|\\r\\n]+"," ").trim();
System.out.println(str);

This above example works for tabSpaces, newLines, and normal spaces. And I have used the trim method of java.lang.String to remove all the additional spaces in 'str'. I hope this helps you and other amazing people here.


try this

([^\r]+\r[^\r])+


Works for me:

import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class Foo {
  public static void main(String args[]) {
    Pattern p = Pattern.compile(".*www.*\\s.*Pig.*");
    String s = "www.foo.com/Archives/monkeys.htm\n"
             + "Description of Monkey's website.\n"
             + "\n"
             + "www.foo.com/Archives/pigs.txt\n"
             + "Description of Pig's website.\n"
             + "\n"
             + "www.foo.com/Archives/kitty.txt\n"
             + "Description of Kitty's website.\n"
             + "\n"
             + "www.foo.com/Archives/apple.htm\n"
             + "Description of Apple's website.\n";
    Matcher m = p.matcher(s);
    if (m.find()) {
      System.out.println(m.group());
    } else {
      System.out.println("ERR: no match");
    }
  }
}

Perhaps the problem was with the way you were using the Pattern and Matcher objects?


This version matches newlines that may be either Windows (\r\n) or Unix (\n)

Pattern p = Pattern.compile("(www.*)((\r\n)|(\n))(.*Pig.*)");
String s = "www.foo.com/Archives/monkeys.htm\n"
           + "Description of Monkey's website.\n"
           + "\r\n"
           + "www.foo.com/Archives/pigs.txt\r\n"
           + "Description of Pig's website.\n"
           + "\n"
           + "www.foo.com/Archives/kitty.txt\n"
           + "Description of Kitty's website.\n"
           + "\n"
           + "www.foo.com/Archives/apple.htm\n"
           + "Description of Apple's website.\n";
Matcher m = p.matcher(s);
if (m.find()) {
  System.out.println("found: "+m.group());
  System.out.println("website: "+m.group(1));
  System.out.println("description: "+m.group(5));
}
System.out.println("done");
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜