Другие показали, как это можно сделать с помощью lookhehind, но я бы хотел привести аргумент в пользу того, что вообще не использовал lookarounds.Рассмотрим это решение ( демо здесь ):
s/\G([^*\\]*(?:\\.[^*\\]*)*)\*/$1%/g;
Основная часть регулярного выражения, [^*\\]*(?:\\.[^*\\]*)*
, является примером идиомы "развернутого цикла" Фридла.Он потребляет как можно больше отдельных символов, кроме звездочки или обратной косой черты, или пар символов, состоящих из обратной косой черты, за которой следует что угодно.Это позволяет избежать использования звездочек без экранирования, независимо от того, сколько им предшествует обратной косой черты (или других символов).
\G
привязывает каждое совпадение к позиции, где закончилось предыдущее совпадение, или к началуввод, если это первая попытка совпадения.Это препятствует тому, чтобы механизм регулярных выражений просто пропускал экранированные обратные слэши и в любом случае сопоставлял неэкранированные звездочки.Таким образом, каждая итерация контролируемого совпадения /g
потребляет все до следующей неэкранированной звездочки, захватывая все, кроме звездочки в группе # 1.Затем он снова подключается, и *
заменяется на %
.
Я думаю, что это, по крайней мере, так же легко читаемо, как приближающийся взгляд, и легче для понимания.Для этого требуется поддержка \G
, поэтому он не будет работать в JavaScript или Python, но он прекрасно работает в Perl.