пятница, 18 марта 2011 г.

Жабо-регэкспы

Почему-то считал, что джава умеет проводить лишь простейший поиск с помощью регэкспов, однако оказалось, что захват групп, замена - все это также возможно.
Появилась задача передать значение длины промежутка времени, выраженное в минутах, часах, днях, месяцах, годах. Что-то вроде 1d для 1 дня, 3M для 3 месяцев, 75m для 75 минут и т.д. Для разбора строки с таким значением идеально подходит регэксп с захватом групп. Числовое значение выделяем в одну группу, значение единицы времени в другую. Вот регэксп, к которому я пришел:
^([1-9][0-9]*)(y|M|d|H|m|s)$
здесь ^ - начало строки, $ - конец строки. Эти символы добавлены, чтобы исключить какие-либо еще посторонние символы. Первая группа ^([1-9][0-9]*) захватывает числовое значение. Значения вида "01" или "-2" не подходят. Вторая группа (y|M|d|H|m|s) захватывает значение единицы времени. Соответствующий джава-код для обработки значения с помощью этих групп:
            Pattern pattern = Pattern.compile(^([1-9][0-9]*)(y|M|d|H|m|s)$);
       Matcher matcher = pattern.matcher(value);
       boolean matchFound = matcher.find();

       if (matchFound) {
           String numberValue = matcher.group(1);
           String unitValue = matcher.group(2);
           int number = Integer.parseInt(numberValue);
           //do something
       }

Весьма все просто.

Задача номер два заключала в себе необходимость формата строки, задающей путь в файловой системе в зависимости от даты. Использовался синтаксис аналогичный FileNamePattern в log4j. Пример:
%d{yyyy}/%d{MM}/msg.%d{yyyy-MM-dd}.gz
Для 18 марта 2011 года из этого шаблона должно получиться 2011/03/msg.2011-03-18.gz
То есть по сути следует заменить все вхождения %d{...} соответствующими значениями переданной даты, шаблон внутри %d{...} аналогичен используемому в SimpleDateFormat. Вот код который производит необходимое форматирование:
Pattern pattern = Pattern.compile("%d\\{(.*?)\\}");
Matcher matcher = pattern.matcher(pathPattern);
String path = pathPattern;
       
while (matcher.find()) {
      SimpleDateFormat dateFormat = new SimpleDateFormat(matcher.group(1));
      path = matcher.replaceFirst(dateFormat.format(date));
      matcher.reset(path);
}

Здесь мы последовательно в цикле находим вхождение паттерна, захватываем группу, форматируем ее с помощью SimpleDateFormat и производим необходимую замену в входной строке шаблона. Выход из цикла происходит, когда в результате не найдено ни одного блока %d{...}

Комментариев нет:

Отправить комментарий