繁体   English   中英

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

[英]Java Regular Expression to find multiple lines of a specific length

我正在尝试使用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的东西不允许'。' 字符或花括号来指定精确的行长度?

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

\\r?\\n

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

试试这个正则表达式:

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

正则表达式在此测试

在以下正则表达式中:

(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

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

这应该工作:

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)匹配最后一行没有行尾的B行

Opsss,我用8而不是50来增加可读性。

点和大括号工作正常; 这是你的正则表达式的其余部分是错的。 看一下这个:

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

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

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

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

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

当然,这是Java的slackbashy字符串表示法,就像你可能传递给Pattern.compile 更合理的语言允许您简单地使用:

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

但是,Java的正则表达从未像现在这样合理,甚至这实际上也是对它们实际上有多糟糕的严重低估。 Java 对空白检测支持不足只是其正则数据中无数的问题之一。

祝你好运:你需要它。

这也应该有效:

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM