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

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

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”,它似乎仍无法正常工作。

这些行可能在文件中以\r\n分隔。 \r \n (回车)和\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标准定义的其他几个行分隔符。 它相当于:

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

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

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

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

为了将来参考,还可以将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()。

尝试这个

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

适合我:

 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对象的方式?

此版本匹配可能是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");