шаблон Java с символами табуляции - PullRequest
1 голос
/ 22 ноября 2011

у меня есть файл с такими строками:

string1 (tab) sting2 (tab) string3 (tab) string4

Я хочу получить из каждой строки, string3 ... Все, что я сейчас получаю из строк, это то, что string3 находится между вторым и третьим символом табуляции. можно ли взять его с рисунком типа

Pattern pat = Pattern.compile(".\t.\t.\t.");

Ответы [ 3 ]

6 голосов
/ 22 ноября 2011
String string3 = tempValue.split("\\t")[2];
5 голосов
/ 22 ноября 2011

Звучит так, как будто вы просто хотите:

foreach (String line in lines) {
    String[] bits = line.split("\t");
    if (bits.length != 4) {
        // Handle appropriately, probably throwing an exception
        // or at least logging and then ignoring the line (using a continue
        // statement)
    }
    String third = bits[2];
    // Use...
}

(Вы можете экранировать строку, так что механизм регулярных выражений должен анализировать обратную косую черту как t, но вам не нужно. Вышеописанное работает нормально.)

Другой альтернативой встроенному методу String.split, использующему регулярные выражения, является класс Guava Splitter. Вероятно, здесь нет необходимости, но об этом стоит знать.

РЕДАКТИРОВАТЬ: Как отмечено в комментариях, если вы собираетесь многократно использовать один и тот же шаблон, более эффективно скомпилировать один Pattern и использовать Pattern.split:

private static final Pattern TAB_SPLITTER = Pattern.compile("\t");

...

String[] bits = TAB_SPLITTER.split(line);
3 голосов
/ 22 ноября 2011

Если вы хотите регулярное выражение, которое захватывает только третье поле и ничего больше, вы можете использовать следующее:

String regex = "(?:[^\\t]*)\\t(?:[^\\t]*)\\t([^\\t]*)\\t(?:[^\\t]*)";
Pattern pattern = Pattern.compile(regex);

Matcher matcher = pattern.matcher(input);
if (matcher.matches()) {
  System.err.println(matcher.group(1));
}

Я не знаю , будет ли это работать лучшечем split("\\t") для анализа большого файла.

ОБНОВЛЕНИЕ

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

/** Simple split parser */
static class SplitParser implements Parser {
    public String parse(String line) {
        String[] fields = line.split("\\t");
        if (fields.length == 4) {
            return fields[2];
        }
        return null;
    }
}

/** Split parser, but with compiled pattern */
static class CompiledSplitParser implements Parser {
    private static final String regex = "\\t";
    private static final Pattern pattern = Pattern.compile(regex);

    public String parse(String line) {
        String[] fields = pattern.split(line);
        if (fields.length == 4) {
            return fields[2];
        }
        return null;
    }
}

/** Regex group parser */
static class RegexParser implements Parser {
    private static final String regex = "(?:[^\\t]*)\\t(?:[^\\t]*)\\t([^\\t]*)\\t(?:[^\\t]*)";
    private static final Pattern pattern = Pattern.compile(regex);

    public String parse(String line) {
        Matcher m = pattern.matcher(line);
        if (m.matches()) {
            return m.group(1);
        }
        return null;
    }
}

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

  • split: 2768,8 мс
  • скомпилированный сплит: 1041,5 мс
  • регулярное выражение группы: 1015,5 мс

Ясно, что важно скомпилировать ваш шаблон , а не полагаться на String.split , если вы собираетесь использовать его несколько раз.

Результатна скомпилированном регулярном выражении split против группы не является окончательным на основании этого тестирования.И, возможно, регулярное выражение может быть улучшено для повышения производительности.

UPDATE

Еще одна простая оптимизация состоит в том, чтобы повторно использовать Matcher, а не создавать по одной итерации цикла.

static class RegexParser implements Parser {
    private static final String regex = "(?:[^\\t]*)\\t(?:[^\\t]*)\\t([^\\t]*)\\t(?:[^\\t]*)";
    private static final Pattern pattern = Pattern.compile(regex);

    // Matcher is not thread-safe...
    private Matcher matcher = pattern.matcher("");

    // ... so this method is no-longer thread-safe
    public String parse(String line) {
        matcher = matcher.reset(line);
        if (matcher.matches()) {
            return matcher.group(1);
        }
        return null;
    }
}
...