Регулярное выражение для замены классов css в html-коде

#php #html #regex #replace #smarty

#php #HTML #регулярное выражение #заменить #умный

Вопрос:

Я ищу регулярное выражение для preg_replace в php, которое заменяет имена классов в html-файлах на уменьшенные имена классов. Я делаю это в процессе минимизации css. Я получил ассоциативный массив с именами классов в качестве ключей и заменами в качестве значений. Т.е.:

$myReplacements = array('fonts' => 'f',
'label' => 'l',
'tiny' => 't')

Эти замены должны выполняться только при точном совпадении, но не в классе типа ‘fonts-small-size’. Мое регулярное выражение для этого:

 /"((.*[^"]?)?(} | |}))?fonts(( {| |{)(.*[^"])?)?"/
  

с помощью replaceregex:

 "$2$3f$5$6"
  

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

 $forcedReplacements = array('ui-icon-' => 'ui-')
  

Эти замены должны быть выполнены в классах типа ‘ui-icon-thumbs-up’ и должны быть заменены на ‘ui-thumbs-up’. Мое регулярное выражение для этого:

 /"(.*)ui-icon-(.*)"/
  

с помощью replaceregex:

 "$1ui-$2"
  

HTML-файл, в котором я хочу заменить имена этих классов, имеет следующее содержимое:

 {if !$isSmallFontCheckDisabled}
    <span class="{if $smallFontFromCharacters}fonts tiny{/if}{if $hasStandardLabel} fonts label{/if}">
{/if}
  

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

В большинстве случаев замены работают довольно хорошо. У меня проблема, если я получил файл шаблона с атрибутом class, содержащий один и тот же класс дважды (это может произойти, если я получил if / else-smarty-block). Затем заменяется только один из двух.

Приведенный выше фрагмент шаблона заменен на:

 {if !$isSmallFontCheckDisabled}
    <span class="{if $smallFontFromCharacters}fonts t{/if}{if $hasStandardLabel} f l{/if}">
{/if}
  

Может ли кто-нибудь помочь мне с моим регулярным выражением для замены всех вхождений шаблонов?

Комментарии:

1. Не могли бы вы предоставить уменьшенный файл или хотя бы его фрагмент?

2. Фрагменты — это фрагменты шаблона, которые я опубликовал. Первый — это не уменьшенный фрагмент. Второй — это тот же уменьшенный фрагмент (шрифты => f, крошечный => t, метка => l)

3. Что ж, в таком случае не следует ли вам опубликовать фрагмент, где ваше регулярное выражение завершается с ошибкой, а не тот, где выражение работает нормально 🙂 Вы пытались добавить g (глобальный) модификатор, который означает — не возвращать при первом совпадении. Итак, попробуйте изменить ваше выражение на это /regular-expression/g

4. модификатор g не работает с preg_replace и также не нужен ( php.net/manual/de/reference.pcre.pattern.modifiers.php ) Как я уже писал, это всегда успешно, если внутри атрибута class дважды нет класса

Ответ №1:

Вы не хотите использовать preg_replace, вы хотите использовать preg_replace_callback(). Извлеките атрибут class из тега, разделите на пробелы, обработайте каждый элемент результирующего массива и затем вставьте его обратно вместе. Что-то вроде этого…

 $line = preg_replace_callback(
    '/(<[^<] class=")([^"]*)(")/',
    function ($matches) {
        $classes = explode(' ', $matches[2])
            /*
                Do your class name replacements here
            */
        return $matches[1].(implode(' ', $classes)).$matches[3];
    },
    $line
);
  

Ответ №2:

Надеюсь, это поможет…

Мой вариант использования:

Добавьте дополнительный класс (css) к атрибуту class для html-тега

Демонстрация: https://regex101.com/r/YZ1Nre/2

Регулярное выражение:

 /(?<opening_tag><input)(?<attributes_before_class>.*)(?<class_attribute_start>class=')(?<class_value>.*?)(?<class_attribute_end>')(?<attributes_after_class>.*)(?<closing_tag>/>)/
  

Подстановка:

 ${opening_tag}${attributes_before_class}${class_attribute_start}${class_value} uk-width-1-1 ${class_attribute_end}${attributes_after_class}${closing_tag}
  

Тестовая строка:

   <input name='input_4' id='input_2_4' type='text' value='' class='large'  tabindex='1'   aria-required="true" aria-invalid="true" />
  

Результат:

  <input name='input_4' id='input_2_4' type='text' value='' class='large uk-width-1-1'  tabindex='1'   aria-required="true" aria-invalid="true" />
  

PHP-код:

 $re = '/(?<opening_tag><input)(?<attributes_before_class>.*)(?<class_attribute_start>class=')(?<class_value>.*?)(?<class_attribute_end>')(?<attributes_after_class>.*)(?<closing_tag>/>)/';
$str = 'Your test string here';
$new_css_class = 'uk-width-1-1';

$subst = '${opening_tag}${attributes_before_class}${class_attribute_start}${class_value} '.$new_css_class.' ${class_attribute_end}${attributes_after_class}${closing_tag}';

// if the named group replacing doesnt work, just use the indices as references
//$subst = '${1}${2}${3}${4} uk-width-1-1 ${5}${6}${7}';

$result = preg_replace($re, $subst, $str);

echo "The result of the substitution is ".$result;