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

Тема в разделе "Perl, Python, Ruby", создана пользователем babahalki, 21 ноя 2017.

  1. babahalki

    babahalki

    Регистр.:
    6 май 2016
    Сообщения:
    246
    Симпатии:
    100
    Коллеги. Вчера возникла необходимость более или менее сложной замены текста по регулярке в ~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}
     
    Последнее редактирование: 21 ноя 2017
  2. kevinbell

    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
    
     
    Последнее редактирование: 12 фев 2020