Java Regular Expression用于查找特定长度的多行

时间:2010-11-22 17:55:03

标签: java regex

我正在尝试使用Java regexp来匹配跨越多行的模式。该模式有一行以'A'开头,后跟正好50个字符,然后是一行或多行,以'B'开头,后跟正好50个字符:

A...    //  exactly 50 chars after the A
B...
B...

Java正则表达式似乎并不支持这一点。

这是一个适用于A和B一行的正则表达式:

A.{50}[\\n[\\n\\r]]B.{50}[\\n[\\n\\r]]

这是相同的正则表达式修改,以找到一个或多个B行:

A.{50}[\\n[\\n\\r]][B.{50}[\\n[\\n\\r]]]+

此正则表达式仅在第一个B行上找到前导B字符。

我使用[\\n[\\r\\n]]来处理DOS和UNIX换行符。打开MULTILINE模式不会影响结果。

问题似乎是当我使用带有'+'的括号将B行的正则表达式转换为可以捕获多行的字符类时。

Java regexp是否存在不允许'。'的问题。字符或花括号来指定确切的行长度?

6 个答案:

答案 0 :(得分:0)

要处理Unix和Dos样式换行符,您可以使用:

\\r?\\n

另外,您对一个或多个B行进行分组的方式不正确,您使用[]进行分组,您应该使用(?: )代替。

试试这个正则表达式:

A.{50}\\r?\\n(?:B.{50}(?:\\r?\\n)?)+

Regex tested here

答案 1 :(得分:0)

在以下正则表达式中:

(A[^\r\n]{50}(\r\n|\n))(B[^\r\n]{50}(\r\n|\n))+

我使用[^\r\n]来匹配任何不是\r\n的字符。例如,如果您有数字,则可以将其替换为[\d]

请参阅http://www.myregextester.com/?r=b7c3ca56

在示例中,正则表达式匹配除最后一行之外的所有内容。

答案 2 :(得分:0)

这应该有效:

String input = "A1234567890\nA12345678\nA12345678\nB12345678\nA123456\nA1234567\nZA12345678\nB12345678\nA12345678\nB12345678\nB12345678\nB12345678\nB1234567\nA12345678\nB12345678";

String regex = "^A.{8}$((\\r|\\r\\n|\\n)^B.{8}$)+(\\r|\\r\\n|\\n|\\z)";

Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
Matcher matcher = pattern.matcher(input);

while (matcher.find()) {
System.out.println("matches from " + matcher.start() + " to " + matcher.end());
}

注意:

  1. 使用^$MULTILINE以避免匹配以“ZA”开头的行。
  2. 使用(\\r|\\r\\n|\\n)来匹配unix,windows和旧的mac-os行。
  3. 使用(\\r|\\r\\n|\\n|\\z)匹配最后一行没有行尾
  4. 的B行

    Opsss,我使用8代替50来提高可读性。

答案 3 :(得分:0)

圆点和花括号可以正常工作;这是你的正则表达式的其余部分是错的。看看这个:

Pattern p = Pattern.compile("^A.{50}(?:(?:\r\n|[\r\n])B.{50})+$");

(?:\r\n|[\r\n])匹配CRLF序列,仅CR或仅LF。 (我本可以像你一样使用两个反斜杠,但这也有效。)

如果您正在使用正则表达式从一些较大的文本中提取匹配项,您将需要在MULTILINE模式下编译它,以便^$锚点可以在行边界匹配。如果它应匹配整个字符串,请将其保留为默认模式,以便它们仅匹配字符串的开头和结尾。

答案 4 :(得分:0)

匹配换行符序列的正确方法是:

"(?:(?>\\u000D\\u000A)|[\\u000A\\u000B\\u000C\\u000D\\u0085\\u2028\\u2029)"

当然,正如您可能传递给Pattern.compile一样,这是Java的松散字符串表示法。更合理的语言可以让您轻松完成:

(?:(?>\x0D\x0A)|\v)

然而,Java的正则表达从未如此合理,甚至这实际上是对how bad they really are的轻描淡写。 Java的poor support for whitespace detection只是其正则数据中无数的麻烦点之一。

祝你好运:你需要它。 ☹

答案 5 :(得分:0)

这也应该有效:

Pattern regex = Pattern.compile("^A.{50}$\\s+(?:^B.{50}$\\s*)+(?:^|\\z)", Pattern.MULTILINE);

这背后的原因是^匹配在行的开头,$匹配行的末尾,(可选的)换行符之前,\s匹配包含\r\n的空白。由于我们在$^之间使用它,因此它只能匹配换行符而不能匹配其他空格。

(?:^|\\z)用于确保我们在B行的最后一次重复之后不会意外匹配行中的任何前导空格。如果行永远不会以空格开头,则可以删除该位。