Java中的RegEx:如何处理换行符

问题描述 投票:22回答:5

我目前正在尝试学习如何使用正则表达式,所以请忍受我的简单问题。例如,假设我有一个输入文件,其中包含由换行符分隔的一堆链接:

www.foo.com/Archives/monkeys.htm Monkey的网站描述。

www.foo.com/Archives/pigs.txt Pig的网站描述。

www.foo.com/Archives/kitty.txt Kitty网站的描述。

www.foo.com/Archives/apple.htm Apple网站的描述。

如果我想获得一个网站及其描述,这个正则表达式似乎适用于测试工具:.*www.*\\s.*Pig.*

但是,当我尝试在我的代码中运行它时似乎不起作用。这个表达是否正确?我尝试用“\ n”替换“\ s”,但它似乎仍无法正常工作。

java regex line-breaks
5个回答
49
投票

这些行可能在您的文件中由\r\n分隔。 \r(回车)和\n(换行)都被认为是Java正则表达式中的行分隔符,而.元字符将不会与它们中的任何一个匹配。 \s将匹配这些角色,因此它消耗\r,但是留下.*以匹配\n,它失败了。您的测试人员可能只使用\n来分隔\s消耗的线条。

如果我是对的,将\s更改为\s+[\r\n]+应该可以使它工作。在这种情况下,这可能就是您需要做的所有事情,但有时您必须恰好匹配一个行分隔符,或者至少跟踪您匹配的数量。在这种情况下,您需要一个与三种最常见的行分隔符类型中的任何一种完全匹配的正则表达式:\r\n(Windows / DOS),\n(Unix / Linus / OSX)和\r(旧版Mac)。这些中的任何一个都可以:

\r\n|[\r\n]

\r\n|\n|\r

更新:从Java 8开始,我们有另一种选择,\R。它匹配任何行分隔符,不仅包括\r\n,还包括Unicode standard定义的其他几个行分隔符。它相当于:

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

以下是您可以使用它的方法:

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

i选项使其不区分大小写,并且m将其置于多线模式,允许^$在线边界匹配。


12
投票

为了将来参考,还可以将Pattern.DOTALL标志用于“。”。甚至匹配\ r或\ n。

例:

假设我们正在解析像这样的一个http标题行的字符串(每行以\ 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

这种模式:

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

可以使用“matcher.group(1)”解析位置值。

“。”在上面的模式中将匹配\ r和\ n,所以上面的模式实际上可以从http标题行解析'Location',其中可能在目标行之前或之后有其他标题(不是这是推荐的方式)解析http标头)。

此外,您可以在模式中使用“?s”来实现相同的效果。

如果你这样做,你可能最好使用Matcher.find()。


1
投票

试试这个

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

0
投票

适合我:

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");
    }
  }
}

问题可能在于你使用Pattern和Matcher对象的方式?


0
投票

此版本匹配可能是Windows(\ r \ n)或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");
© www.soinside.com 2019 - 2024. All rights reserved.