RegExp: как исключить совпавшие группы из $N?

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

el = '<div style="color:red">123</div>';
el.replace(/(<div.*>)(\d+)(<\/div>)/g, '$1<b>$2</b>$3');
// expecting result: <div style="color:red"><b>123</b></div>

После поиска в Google я обнаружил, что (?: ... ) в регулярных выражениях означает игнорирование группового соответствия, таким образом:

el.replace(/(?:<div.*>)(\d+)(?:<\/div>)/g, '<b>$1</b>');
// returns <b>123</b>

но мне нужен ожидаемый результат из 1-го примера.

Есть ли способ их исключить? просто написать replace(/.../, '<b>$1</b>')?

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


person mjey    schedule 01.04.2012    source источник
comment
Нет, ты не можешь этого сделать. .replace заменит все совпадение.   -  person Felix Kling    schedule 01.04.2012
comment
Нет возможности сделать это через DOM?   -  person Gumbo    schedule 01.04.2012
comment
DOM — это не цель. Просто пример.   -  person mjey    schedule 01.04.2012


Ответы (2)


Итак, вы хотите получить тот же результат, используя только замену <b>$1</b>?

В вашем случае достаточно replace(/\d+/, '<b>$&</b>').

Но если вы хотите убедиться, что вокруг числа есть теги div, вы можете использовать обходы и \K, как в следующем выражении. За исключением того, что JS не поддерживает ретроспективный просмотр и \K, так что вам не повезло, вы должны использовать для этого группу захвата в JS.

<div[^>]*>\K\d+(?=</div>)
person Qtax    schedule 01.04.2012
comment
Упс, я ошибся. el.replace(/(?:<div.*>)(\d+)(?:<\/div>)/g, '<b>$1</b>'); возвращает только <b>123</b> - person mjey; 01.04.2012
comment
Да, цель состоит в том, чтобы сопоставить цифры вокруг указанного тега. Печально, что js не поддерживает \K - person mjey; 01.04.2012
comment
Хм, этот '<div style="color:red">123</div><div>555</div>'.replace(/(?!<div.*>)(\d+)(?=<\/div>)/g, '<i>$1</i>') работает (результат: "<div style="color:red"><i>123</i></div><div><i>555</i></div>"). Но я не понимаю, почему это работает, так как (?! означает отрицательный прогноз. (?<= не работает. - person mjey; 01.04.2012
comment
@mjey работает, потому что \d+ работает. Попробуйте на строке 123</div>. Отрицательный просмотр вперед означает, что все, что впереди, должно не совпадать с выражением. - person Qtax; 01.04.2012
comment
Хорошо, понял. Но, как видите, положительный прогноз работает (хром 18) :) - person mjey; 01.04.2012

Нет ничего плохого в замене значения '$1<b>$2</b>$3'. Я бы просто изменил ваше регулярное выражение на это:

el = '<div style="color:red">123</div>';
el.replace(/(<div[^>]*>)(\d+)(<\/div>)/g, '$1<b>$2</b>$3');

Изменение того, как он соответствует первому тегу div, сохраняет полное совпадение тегов div, но гарантирует, что оно соответствует минимально возможному до закрытия > первого тега div, а не максимально возможному.

С вашим регулярным выражением вы не получите то, что хотели, с этой входной строкой:

el = '<div style="color:red">123</div><div style="color:red">456</div>';

Проблема с использованием чего-то вроде:

el.replace(/\d+/, '<b>$&</b>')

это не работает должным образом с такими вещами, как это:

el = '<div style="margin-left: 10px">123</div>'

потому что он подбирает числа внутри тега div.

person jfriend00    schedule 01.04.2012
comment
она соответствует минимально возможному до закрытия, что может не сработать, как вы думаете. В <div>x</div><div>123</div> $1 будет захвачено <div>x</div><div>, как в исходном выражении OP. - person Qtax; 01.04.2012
comment
@Qtax - я изменил свое регулярное выражение, чтобы сделать его более надежным в этом отношении. - person jfriend00; 01.04.2012