Регулярное выражение Java от регулярного выражения типа Perl - PullRequest
3 голосов
/ 28 сентября 2011

Я пытаюсь извлечь часы, минуты, секунды и наносекунды из метки времени строки в файле журнала. Вот строка ввода, с которой я тестирую:

 SOME_TEXT,+09:30:01.040910105,SOME_TEXT,SOME_TEXT,SOME_TEXT

В Perl / Python я бы использовал следующее регулярное выражение для группировки интересующих меня полей:

 (\d\d)\:(\d\d)\:(\d\d)\.(\d{9})

Вы можете проверить, что регулярное выражение работает с тестовой строкой на http://regexpal.com, если вам интересно.

Итак, я попытался написать простую программу на Java, которая может извлекать поля:

import java.util.regex.*;

public class Driver
{
  static public void main(String[] args)
  {
    String t = new String("SOME_TEXT,+09:30:01.040910105,SOME_TEXT,SOME_TEXT,SOME_TEXT");
    Pattern regex = Pattern.compile("(\\d\\d):(\\d\\d):(\\d\\d)\\.(\\d{9})");
    Matcher matches = regex.matcher(t);
    for (int i=1; i<matches.groupCount(); ++i)
    {
      System.out.println(matches.group(i));
    }
  }
}

Однако мое регулярное выражение не было правильно переведено. Следующее исключение показывает, что не найдено совпадений:

 Exception in thread "main" java.lang.IllegalStateException: No match found
   at java.util.regex.Matcher.group(Matcher.java:485)
   at Driver.main(Driver.java:12)

Как мне правильно перевести регулярное выражение из стиля Perl / Python в Java?

Ответы [ 4 ]

3 голосов
/ 28 сентября 2011

Само регулярное выражение в порядке.Однако есть две проблемы с кодом:

  1. вам нужно позвонить Matcher.find();
  2. вам нужно исправить петлю for (он должен использовать <= вместо <).

Вот исправленная версия:

public class Driver
{
  static public void main(String[] args)
  {
    String t = new String("SOME_TEXT,+09:30:01.040910105,SOME_TEXT,SOME_TEXT,SOME_TEXT");
    Pattern regex = Pattern.compile("(\\d\\d):(\\d\\d):(\\d\\d)\\.(\\d{9})");
    Matcher matcher = regex.matcher(t);
    while (matcher.find()) {
        for (int i=1; i<=matcher.groupCount(); ++i)
        {
          System.out.println(matcher.group(i));
        }
    }
  }
}

Это распечатывает:

09
30
01
040910105
2 голосов
/ 29 сентября 2011

Java нарушает стиль Perl, создавая сложность там, где это не нужно.Если вы хотите правильно выполнять регулярные выражения в Java, взгляните на MentaRegex .Ниже приведены несколько примеров:

Метод соответствует возвращает логическое значение, указывающее, есть ли у нас совпадение с регулярным выражением или нет.

matches("Sergio Oliveira Jr.", "/oliveira/i" ) => true

Метод match возвращает массив с сопоставленными группами.Таким образом, он не только сообщает вам, есть ли у вас совпадение, но также возвращает группы совпадений, если у вас есть совпадение.

match("aa11bb22", "/(\\d+)/g" ) => ["11", "22"]

Метод sub позволяет выполнять замены срегулярное выражение.

sub("aa11bb22", "s/\\d+/00/g" ) => "aa00bb00"

Поддерживает глобальное регулярное выражение без учета регистра.

match("aa11bb22", "/(\\d+)/" ) => ["11"]
match("aa11bb22", "/(\\d+)/g" ) => ["11", "22"]
matches("Sergio Oliveira Jr.", "/oliveira/" ) => false
matches("Sergio Oliveira Jr.", "/oliveira/i" ) => true

Позволяет изменить escape-символ в случае, если вам не нравится видеть так много '\'.

match("aa11bb22", "/(\\d+)/g" ) => ["11", "22"]
match("aa11bb22", "/(#d+)/g", '#' ) => ["11", "22"]
0 голосов
/ 28 сентября 2011

О, нет! Я скопировал ваши коды и обернул if (matches.find()) { ...}, затем работал. ты нуждаешься в этом.

и наносекунд не было. Вы должны сделать это изменение:

for (int i = 1; i <= matches.groupCount(); ++i)
-------------------^
0 голосов
/ 28 сентября 2011

По умолчанию регулярные выражения java совпадают со всей строкой, вы должны добавить. * В начало и конец:

Pattern regex = Pattern.compile(".*(\\d\\d):(\\d\\d):(\\d\\d)\\.(\\d{9}).*");

и это должно работать, с другими исправлениями для вашего цикла for по мере необходимости: -)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...