Начать регулярное выражение в середине строки в Java - PullRequest
2 голосов
/ 01 августа 2010

Я анализирую относительно сложное выражение в Java с помощью регулярных выражений + некоторый ручной анализ. То, что я сейчас делаю, это удаление того, что я уже проанализировал из строки, поэтому у меня есть следующая вещь, которую нужно проанализировать прямо в начале строки.

Я хотел бы изменить это, чтобы у меня была переменная int pos, и я не изменяю строку. Однако ни в классах Pattern, ни в классах Matcher, похоже, нет чего-то, что помечало бы индекс первого символа для сопоставления. Есть ли способ сделать это?

(я знаю, что могу просто передать str.substring(pos) в Matcher, но я думаю, что это намного дороже и немного усложняет мой код, так как я часто использую методы start() и end() ).

Ответы [ 6 ]

7 голосов
/ 01 августа 2010

A java.util.regex.Matcher пытается найти совпадения в области , которая по умолчанию используется для всего входа, но может быть явно задана для определенного поддиапазона.

Из документации:

Сопоставитель находит совпадения в подмножестве своего ввода, которое называется region . По умолчанию область содержит все входные данные сопоставителя. Регион можно изменить с помощью метода region(int start, int end) и запросить с помощью методов regionStart и regionEnd. Способ, которым границы области взаимодействуют с некоторыми конструкциями образца, может быть изменен. Подробнее см. useAnchoringBounds и useTransparentBounds.

Помните, что, как и многие методы в классах библиотеки Java, индекс start равен включительно , но индекс end равен эксклюзиву .


Отрывок

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

    String text = "012 456 890 234";
    Pattern ddd = Pattern.compile("\\d{3}");
    Matcher m = ddd.matcher(text).region(3, 12);
    while (m.find()) {
        System.out.printf("[%s] [%d,%d)%n",
            m.group(),
            m.start(),
            m.end()
        );
    }

Приведенные выше отпечатки ( как видно на ideone.com ):

[456] [4,7)
[890] [8,11)

О границах привязки и прозрачных границах

Как уже упоминалось ранее, когда вы указываете регион, вы можете изменить поведение некоторых шаблонных конструкций в зависимости от того, что вам нужно.

привязка границы делает границы области соответствующими различным сопоставлениям границ (^, $ и т. Д.).

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

По умолчанию Matcher использует как привязку , так и непрозрачные границы. Это применимо к большинству сценариев сопоставления субрегионов, но вы можете установить свою собственную комбинацию в зависимости от ваших потребностей.

6 голосов
/ 01 августа 2010

Matcher.find (int start) было бы полезно для вас

1 голос
/ 01 августа 2010

Метод region() - это то, что вы ищете. Каждый раз, когда вы сопоставляете что-либо, вы перемещаете начальную позицию региона туда, где закончился этот матч. Что касается Matcher, то теперь это начало ввода.

Если вы установите опцию useAnchoringBounds(), вы можете рассматривать начало региона так, как если бы оно было началом текста (т. Е. ^ или \A будет соответствовать) и если вы установите useTransparentBounds(), внешний вид и границы слов все равно будут «видеть» предыдущий текст. И вы можете использовать оба варианта одновременно.

Если вы всегда хотите, чтобы следующий матч начинался точно в начале региона, вы можете даже использовать lookingAt() вместо find() - единственное хорошее применение Я когда-либо нашел для этого метода. ;)

1 голос
/ 01 августа 2010

Как насчет использования Matcher.region (int start, int end)

Javadoc говорит:

Устанавливает пределы региона этого сопоставителя. Регион - это часть входной последовательности, в которой будет выполняться поиск совпадений. Вызов этого метода сбрасывает сопоставление, а затем задает для области начало с индекса, указанного параметром start, и конца с индексом, указанным параметром end.

0 голосов
/ 01 августа 2010

String.substring - операция с постоянным временем; символьные данные не копируются, но разделяются с исходной строкой. Из исходного кода JDK:

// Package private constructor which shares value array for speed.
String(int offset, int count, char value[]) {
this.value = value;
this.offset = offset;
this.count = count;
}

public String substring(int beginIndex, int endIndex) {
// error checking omitted
return ((beginIndex == 0) && (endIndex == count)) ? this :
    new String(offset + beginIndex, endIndex - beginIndex, value);
}

Так что не стоит беспокоиться о производительности подстроки.

0 голосов
/ 01 августа 2010

Является ли ваше приложение достаточно критичным для производительности, чтобы иметь значение str.substring (pos)?Регулярное выражение будет на несколько порядков медленнее подстроки, поэтому вместо усложнения регулярного выражения просто разбейте его на части.Это был бы мой подход.

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