Java中的正则表达式:如何处理换行符

2022-09-01 01:51:35

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

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

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

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

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

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

但是,当我尝试在我的代码中运行它时,它似乎不起作用。这种说法是否正确?我尝试将“\s”替换为“\n”,但它似乎仍然不起作用。


答案 1

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

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

\r\n|[\r\n]

\r\n|\n|\r

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

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

以下是使用它的方法:

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

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


答案 2

为了将来参考,还可以使用 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标头行解析“位置”,其中目标行之前或之后可能还有其他标头(并不是说这是解析http标头的推荐方法)。

此外,您可以在图案内部使用“?s”来达到相同的效果。

如果你正在这样做,你可能会更好地使用 Matcher.find()。