perl однострочник для умной замены блоков

babahalki

Постоялец
Регистрация
6 Май 2016
Сообщения
247
Реакции
107
Коллеги. Вчера возникла необходимость более или менее сложной замены текста по регулярке в ~15 файлах шаблонов смарти. Сначала вообще делал с помощью sed, но когда нужно было использовать негативный просмотр вперед для исключения нескольких возможных комбинаций, тут возможности sed исчерпались. Перешел на perl. А теперь и perl забуксовал, не могу понять, как сделать.

#замена объектов на массивы (тут все в порядке)
Код:
ls *.tpl | xargs perl -pne 's/(?!\$settings|\$config)(?=.*?)(\$[a-zA-Z0-9\_]+)->([a-zA-Z0-9\_]+)(?=.*?)/\1\[\x27\2\x27\]/g' -i

#замена блока, но только при условии нахождения внутри другого блока
# нужно менять
Код:
$f['name'] на $features[$fid]['name']
только, если он находится внутри
Код:
foreach $options as $o

Такая конструкция срабатывает, но просмотр вперед учитывать отказывается.
Код:
ls *.tpl | xargs perl -pne 's/(\?\=foreach \$options)(\.\*\?)\$f\[\x27name\x27\](\.\*\?)(\?\=\/foreach)/\1\$features\[\$fid\]\[\x27name\x27\]\2/gsm' -i


Образец текста для замены
Код:
      {foreach $features as $f}
      <div class="paramsBox">
                <div class="paramsBoxTitle">
                    <span>{$f['name']}</span>
            </div>
            <ins class="propExpander  expanded"></ins>
         <div class="params">
            <ul class="checkbox">
            {foreach $f['options'] as $k=>$o}
               <li>
                  <input id="option_{$f['id']}_{$k}" type="checkbox" name="{$f['id']}[]" value="{$o['value']|escape}"{if $o['checked']} checked{elseif $o['disabled']} disabled{/if}>
                  <label for="option_{$f['id']}_{$k}"><span>{$o['value']|escape}</span> <i>{if !$o['checked']}({$o['count']}){/if}</i></label>
               </li>
            {/foreach}
            </ul>
         </div>
      </div>
      {/foreach}
 
Последнее редактирование:

kevinbell

Создатель
Регистрация
5 Ноя 2015
Сообщения
18
Реакции
4
#замена блока, но только при условии нахождения внутри другого блока
Код:
perl -i -ne "BEGIN{ \$in=0;\$i=0; }{
m@\{foreach (.*?)\}@ && \$i++ &&   \$1 =~ m@^\\\$features as \\\$f\$@ && (\$in=\$i);    ### ID.start.foreach
m@\{\/foreach@ && \$i--;                                                                ### ID.end.foreach
\$i > 0 && \$i>=\$in &&     s@\\\$f\['name'\]@\\\$features[\\\$fid]['name']@g;          ### DO.REPLACE
print;}" *.tpl

или

perl -i -ne 'BEGIN{$in=0;$i=0;}{m@\{foreach (.*?)\}@&&$i++&&$1=~m@^\$features as \$f$@&&($in=$i);m@\{/foreach@&&$i--;$i>0&&$i>=$in&&s@\$f\[\x27name\x27\]@\$features[\$fid]['name']@g;print;}' *.tpl
 
Последнее редактирование:
Сверху