2010-11-22 2 views
5

Я пытаюсь использовать регулярные выражения Java для соответствия шаблону, который охватывает несколько строк. Шаблон имеет одну строку, которая начинается с «A», а затем ровно 50 символов, а затем одну или несколько строк, которые начинаются с «B», а затем ровно 50 символов:Java Regular Expression для поиска нескольких строк определенной длины

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

Java регулярные выражения, кажется, не поддерживают это однако.

Вот регулярное выражение, которое работает для одного А и один В строке:

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 не влияет на результаты.

Проблема заключается в том, что я использую скобки с символом «+», чтобы превратить регулярное выражение для строки В в класс символов, который может захватывать несколько строк.

Есть ли что-то о регулярных выражениях Java, которые не допускают '.' символ или фигурные скобки, чтобы указать точную длину строки?

+0

Существует одна линия A с 50 символами, следующими за «A», а затем с несколькими строками B с 50 символами после «B». stackoverflow не сохранял новые строки между линиями A и B, которые я показал выше. – 2010-11-22 17:57:30

ответ

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

В этом примере регулярное выражение соответствует всем, кроме последней строки.

+0

Это похоже на работу. – 2010-11-22 18:49:23

0

Для обработки как Unix и Dos стиль новой строки вы можете использовать:

\\r?\\n 

Кроме того, ваш способ группировки одного или нескольких B линий неверен, вы используете [] для группировки, вы должны использовать (?: ) вместо этого.

Попробуйте это регулярное выражение:

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

Regex tested here

+0

Просто ради этого, так как вы разместили рубиновую версию. Вот отличная версия python тестера регулярных выражений http://www.pythonregex.com/ – Falmarri 2010-11-22 18:38:28

+0

Спасибо. Кажется, это работает. – 2010-11-22 18:46:54

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 избежать, чтобы соответствовать строку, начинающуюся с "З".
  2. использование (\\r|\\r\\n|\\n) для соответствия unix, windows и старых линий mac-os.
  3. использование (\\r|\\r\\n|\\n|\\z), чтобы соответствовать последней B линии без конца-строки

Opsss, я использовал 8 вместо 50 увеличить читаемость.

0

Точка и фигурные скобки работают нормально; это остальное ваше регулярное выражение, это неправильно. Проверьте это:

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

(?:\r\n|[\r\n]) соответствует последовательности CRLF, CR только, или только LF. (Я мог бы использовать две спинки, как и вы, но это тоже работает).

Если вы используете регулярное выражение, чтобы срывать матчи из какого-то большего текста, вы хотите скомпилировать его в режиме многострочного так ^ и $ якоря могут совпадать с границами линии. Если предполагается, что она соответствует целой строке, оставьте ее в режиме по умолчанию, поэтому они соответствуют только началу и концу строки.

0

Правильный способ сопоставления последовательности LineBreak является:

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

Это в slackbashy струнной нотации Java, конечно, так же, как вы могли бы перейти к Pattern.compile. Более разумные языки позволяют получить с просто:

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

Но тогда, регулярные выражения в Java никогда не было ничего подобного разумно, и даже это на самом деле грубое преуменьшение для how bad they really are. Java poor support for whitespace detection - это просто одно из бесчисленных проблемных мест регулярных выражений.

Удачи вам. ☹

0

Это должно работать также:

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

Смысл этого в том, что ^ матчей в начале линии, $ матчей в конце строки, перед (по желанию) символа новой строки, и \s соответствует пробелу, который включает \r и \n. Поскольку мы используем его между $ и ^, он может соответствовать только символам новой строки, а не другим пробелам.

(?:^|\\z) используется, чтобы быть уверенным, что мы не случайно сопоставляем любые ведущие пробелы в строке, следующей за последним повторением строки B. Если строки никогда не начинаются с пробелов, вы можете удалить этот бит.