RegEx Advanced: положительный взгляд назад

Это моя тестовая строка:

<img rel="{objectid:498,newobject:1,fileid:338}" width="80" height="60" align="left" src="../../../../files/jpg1/Desert1.jpg" alt="" />

Я хочу получить каждый из сформированных элементов JSON между атрибутом rel. Он работает для первого элемента (objectid).

Вот мой ReqEx, который отлично работает:

(?<=(rel="\{objectid:))\d+(?=[,|\}])

Но я хочу сделать что-то вроде этого, что не работает:

(?<=(rel="\{.*objectid:))\d+(?=[,|\}])

Так что я могу разобрать каждый элемент строки поиска.

Я использую Java-ReqEx


person mpneuried    schedule 21.04.2010    source источник


Ответы (3)


Java (и почти все разновидности регулярных выражений, кроме .NET и JGSoft) не поддерживают бесконечное повторение внутри просмотра назад.

Вместо этого вы можете использовать группы захвата. Кроме того, лучше использовать [^{]* вместо .* и обеспечить границы слов с помощью \b.

rel="\{[^{]*\bobjectid:(\d+)

должно быть достаточно (затем посмотрите на группу захвата 1 для значения атрибута.

person Tim Pietzcker    schedule 21.04.2010

Вы хотите перебрать все пары ключ/значение? Вам не нужно смотреть назад для этого:

String s = 
    "<img rel=\"{objectid:498,newobject:1,fileid:338}\" " +
    "width=\"80\" height=\"60\" align=\"left\" " +
    "src=\"../../../../files/jpg1/Desert1.jpg\" alt=\"\" />";
Pattern p = Pattern.compile(
    "(?:\\brel=\"\\{|\\G,)(\\w+):(\\w+)");
Matcher m = p.matcher(s);
while (m.find())
{
  System.out.printf("%s = %s%n", m.group(1), m.group(2));
}

При первом вызове find() первая часть регулярного выражения соответствует rel="{. При последующих вызовах вторая альтернатива (\G,) соответствует запятой, но только в том случае, если она непосредственно следует за предыдущим совпадением. В любом случае он оставляет вас в очереди для (\w+):(\w+) для соответствия следующей паре ключ/значение, и он никогда не может совпадать где-либо за пределами атрибута rel.

Я предполагаю, что вы применяете регулярное выражение к изолированному тегу IMG, как вы его опубликовали, а не ко всему файлу HTML. Кроме того, регулярному выражению может потребоваться небольшая настройка, чтобы оно соответствовало вашим фактическим данным. Например, вам может понадобиться более общее ([^:]+):([^,}]+) вместо (\w+):(\w+).

person Alan Moore    schedule 21.04.2010

Lookaheads и Lookbehinds могут вообще не содержать произвольных регулярных выражений: большинство движков (включая Java) требуют, чтобы их длина была хорошо известна, поэтому вы не можете использовать в них квантификаторы, такие как *.

В любом случае, почему вы используете просмотр вперед и просмотр назад? Вместо этого используйте группы захвата, это намного проще.

rel="\{.*objectid:(\d+)

Теперь первая группа захвата будет содержать идентификатор.

person Konrad Rudolph    schedule 21.04.2010
comment
Не совсем. Бесконечное повторение не является проблемой при просмотре вперед, только при просмотре назад. - person Tim Pietzcker; 21.04.2010