#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;