Разбор числовых значений с помощью классов регулярных выражений Java - PullRequest
0 голосов
/ 05 октября 2010

В Java я пытаюсь проанализировать данные из выходного файла ASCII. Пример данных выглядит ниже. Значения отформатированы с точностью 5 по шкале 3, и между значениями нет пробелов.

80,234 <- 1 значение </em>
71.01663.129 <- <em>2 значения ...

67.09159.25353.997
56.02759.77859.25057.749
55,86558,46958,64861,72855,969

Какой шаблон регулярного выражения можно использовать для сопоставления числовых значений и разделения их на группы? Шаблон (\ d +. \ D {1,3}) соответствует одному значению. Тем не менее, с указанием количества групп для указанной строки он не дает ожидаемого ответа. Например, я ожидал, что следующее найдет 10 групп.

String testPattern = "68.65761.25659.01057.67657.14857.06457.41658.77861.16268.641";

// create a pattern to match the output
Pattern p = Pattern.compile("(\\d+\\.\\d{1,3}){10}");

Matcher m = p.matcher(testPattern);

if (m.find())
{
    String group = m.group();
}

Ответы [ 4 ]

4 голосов
/ 05 октября 2010

Если они все одинаково отформатированы, возможно, было бы проще просто прочитать 6 символов в виде строки, а затем использовать Double.parseDouble для анализа этого значения из строки в Double?

2 голосов
/ 05 октября 2010

Вы ожидаете, что это каким-то образом вырвет отдельные числа, потому что именно так вы их подбираете, но это не сработает.То, что делает ваше регулярное выражение, захватывает одно число за раз и помещает его в группу # 1.Это происходит десять раз, каждый раз перезаписывая содержимое группы # 1 новым значением.Когда это будет сделано, group() вернет всю строку, как вы обнаружили, в то время как group(1) вернет только десятое число, 68.641.

Это распространенная ошибка, вероятно, из-за отсутствия встроенного Java-в механизме "найти все совпадения"..NET имеет свои Matches() методы, PHP имеет preg_match_all(), Python имеет re.findall(), Perl и JavaScript имеют модификатор /g ... каждый основной вариант имеет механизм для возврата либо массива всех совпадений, либо итератораза спичками или обоими.Но в Java вы должны вызывать find() в цикле while, как продемонстрировал @KennyTM.

Это досадное упущение, но не совсем удивительное для Java.Его эффект заключается в том, чтобы заставить нас писать более многословный, менее идиоматический код, который с самого начала был отличительной чертой Java.Но если вы действительно хотите свести эту задачу к одной строке, есть старый трюк «разбить на части»:

String[] result = source.split("(?=\\B\\d{2}\\.\\d{3})");

... или:

String[] result = source.split("(?<=\\G\\d{2}\\.\\d{3})");
2 голосов
/ 05 октября 2010

Существует только 1 группа с вашим регулярным выражением. Используйте цикл while, чтобы перечислить все из них. (См. http://www.ideone.com/FNRsz):

String testPattern = "68.65761.25659.01057.67657.14857.06457.41658.77861.16268.641";
Pattern p = Pattern.compile("\\d+\\.\\d{1,3}");
Matcher m = p.matcher(testPattern);

while(m.find())   // <---
   System.out.println(m.group());
1 голос
/ 05 октября 2010

Используя Гуава , фиксированная длина Разветвитель будет хорошо работать здесь.

Iterable<String> numbers = Splitter.fixedLength(6).split(testPattern);

Если бы вы создали Function<String, Double> (называемый, скажем, Numbers.doubleParser()), вы могли бы даже легко преобразовать данные в числа. (Очевидно, вы можете использовать BigDecimal или что угодно, а не Double в зависимости от ваших потребностей.)

private static final Splitter SPLITTER = Splitter.fixedLength(6);

...

public void someMethod(String stringToParse) {
  for(Double value : Iterables.transform(SPLITTER.split(stringToParse),
                                         Numbers.doubleParser())) {
    ...
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...