我正在尝试使用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是否存在不允许'。'的问题。字符或花括号来指定确切的行长度?
答案 0 :(得分:0)
要处理Unix和Dos样式换行符,您可以使用:
\\r?\\n
另外,您对一个或多个B
行进行分组的方式不正确,您使用[]
进行分组,您应该使用(?: )
代替。
试试这个正则表达式:
A.{50}\\r?\\n(?:B.{50}(?:\\r?\\n)?)+
答案 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());
}
注意:
^
,$
和MULTILINE
以避免匹配以“ZA”开头的行。(\\r|\\r\\n|\\n)
来匹配unix,windows和旧的mac-os行。(\\r|\\r\\n|\\n|\\z)
匹配最后一行没有行尾 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
行的最后一次重复之后不会意外匹配行中的任何前导空格。如果行永远不会以空格开头,则可以删除该位。