2014-09-24 2 views
0

Я пытаюсь написать регулярное выражение, которое будет соответствовать строке чисел ровно 12 раз (в начале строки может появиться дополнительный номер, который я хотел бы отбросить).Regexp annoyance

Я написал это регулярное выражение, чтобы соответствовать эти цифры, когда все они были как 123.(\ d + \ d +.)

String str3 = "0.0503 0.0485 0.0481 0.0491 0.0494 0.0489 0.0482 0.0485 0.0479 0.0487 0.0495 0.0487";

Pattern dataLinePattern = Pattern.compile("^(\\d+\\.\\d+\\s)?((\\d+\\.\\d+\\s*?){12})$"); Matcher m = dataLinePattern.matcher(str3); if (m.matches()) { System.out.println(m.group(2)); }

ожидается выход:

0,0503 0,0485 0,0481 0,0491 0.0494 0.0489 0.0482 0.0485 0.0479 0.0487 0.0495 0.0487

Однако, когда я пытаюсь что-то вроде

"^(\d+[\.\d]?\t?)?((\d+[\.\d]?\t*?){12})$"

или

"^(\d+(\.\d+)?\t?)?((\d+(\.\d+)?\t*?){12})$"

, чтобы сделать знаков после запятой необязательно, сокращение регулярных выражений выключает первое число и печатает только последние 11 ... Что я делаю не так?

выход:

0.0485 0.0481 0.0491 0.0494 0.0489 0.0482 0.0485 0.0479 0.0487 0.0495 0.0487 (отсутствует 0.0503)

редактировать: решена. вопрос сменился на дополнительный разделитель табуляции \ t *? когда эта вкладка является необязательной для последних 12 номеров, двигатель regexp вернется и ищет совпадение и обнаружит, что последнее число будет совпадать дважды: 0 и 0487 (в этом примере)

переупорядочить регулярное выражение, чтобы установить вкладка в начале каждого номера, а не «может быть» в конце каждого номера, заставляет его работать.

Pattern.compile("([0-9.]+\t)?(([0-9.]+)(\t[0-9.]+){11})");

+0

это работает для меня .. –

+0

Он отлично работает, проверьте http://regex101.com/r/ uO1lR6/1 –

+0

код в первом блоке кода работает, вы пытались использовать 2 альтернативных регулярных выражения внизу? (они почему-то не вставляли правильный формат java, поэтому вам нужно было бы добавить обратную косую черту) –

ответ

1

Попробуйте это:

String str3 = "0.0 0.0503 0.0485 0.0481 0.0491 0.0494 0.0489 0.0482 0.0485 0.0479 0.0487 0.0495 0.0487";  

Pattern dataLinePattern = Pattern 
     .compile(".*\\s+((\\d+(\\.\\d+)?)(\\s+(\\d+(\\.\\d+)?)){11})\\s*$"); 
Matcher m = dataLinePattern.matcher(str3); 

if (m.matches()) { 
    System.out.println(m.group().trim().replaceAll("\\s+", " ")); 
} 

Он печатает:

0.0503 0.0485 0.0481 0.0491 0.0494 0.0489 0.0482 0.0485 0.0479 0.0487 0.0495 0.0487 
+0

Не нравится эти жадные кванторы, но вы направили меня на правильный путь. Паттерн dataLinePattern = Pattern.compile (" ? ([. 0-9] + \\ т) ([. 0-9] (+) (\\ т [0-9.] +), {11}) "); –

+0

Прохладный. Но разве первая группа не нужна? Вы можете просто поставить '. *'. – elias

+0

хорошо использовать. *? на самом деле, но первая группа явно написана так, чтобы сделать регулярное выражение более быстрым. «. *» является жадным и будет фактически соответствовать всей строке, а затем двигатель regexp будет возвращаться через каждый символ в целом, пытаясь сопоставить остальную часть выражения. Это делает шаблон более неэффективным. Дело в том, что с регулярными выражениями вы всегда должны быть настолько ясными, насколько это возможно, для небольших файлов вы можете не видеть никакой разницы, но для больших файлов (думаю, 30 ГБ последовательностей генома) разница может стать огромной. –