2016-04-09 2 views
-1

У меня есть воспроизводимый пример, демонстрирующий странное поведение функции PHP preg_replace. Итак, у меня есть два файла с таким содержанием:preg_replace неправильное или странное поведение в PHP

//new.txt 
<!-- start -->Replacement 2\1<!-- end --> 

//before.txt 
<!-- start -->Text to replace<!-- end --> 

Когда я делаю это:

$regex = "`<!-- start -->(.*?)<!-- end -->`"; 
$replacement = file_get_contents("new.txt"); 
$target = file_get_contents("before.txt"); 
$after = preg_replace($regex, $replacement, $target); 
echo $after; 

печатает:

<!-- start -->Replacement 2Text to replace<!-- end --> 

, которая на самом деле неверно. Но когда я делаю это:

$regex = "`<!-- start -->(.*?)<!-- end -->`"; 
$replacement = "<!-- start -->Replacement 2\1<!-- end -->"; 
$target = "<!-- start -->Text to replace<!-- end -->"; 
$after = preg_replace($regex, $replacement, $target); 
echo $after; 

печатает:

<!-- start -->Replacement 2<!-- end --> 

, который является более правильным (хотя, как вы можете видеть, последний "\ 1" исчез). BTW, если я удалю «\ 1», оба примера начнут работать правильно. Итак, как я могу это исправить?

+0

Интересно, почему люди голосуют вниз, даже если я обеспечил воспроизводимые примеры и мои собственные фрагменты кода. – Jacobian

+0

Кроме того, обратите внимание, что я сказал «неправильное или странное поведение», поэтому я не настаиваю на том, что это ошибка PHP. Наверное, я просто делаю что-то не так. – Jacobian

+0

Итак, если бы я спросил какую-то глупость, почему бы не указать на эту глупость? Зачем это молчаливое голосование? – Jacobian

ответ

2

Здесь происходит большое сочетание разных вещей.

(я пошел с воображаемым ожидаемым результатом <!-- start -->Replacement 2\1<!-- end -->)

Для первой темы, в регулярных выражениях замены, \1является обратной ссылкой. Это будет заменено символами, согласованными в первой скобке в шаблоне. Он также может быть записан как $1.

Вы можете использовать цифры от 1 до 99. Вы можете найти более подробную информацию здесь в PHP doc for regexes и preg_replace (см replacement)

Это объясняет, почему \1 заменяется Text to replace как это часть соответствует по (.*?)

Вторая вещь - запомнить разницу между одинарными кавычками ('str') и двойными кавычками ("str"). В одинарных кавычках обратная косая черта не имеет специального значения (за исключением того, чтобы избежать одиночной кавычки: echo 'str\'str' производит str'str или для самозащиты: echo 'str\\str' производит str\str). Но в двойных кавычках обратная косая черта имеет особое значение и вводит escape-последовательность (\n, \r, ...) и может также представлять символ в восьмеричных обозначениях. Это происходит здесь, в вашей второй строке . Это строка с двойными кавычками, а \1 заменяется символом SOH, который не является видимым символом.

Третье, что строка, считанная из файла, не изменяется, как двойная или одинарная кавычка, вы получаете ее точно так же, как в файле.

Решение: Вам нужно избегать обратной косой черты, но сколько раз нужно?

  • Состояние: функция preg_replace должна Получать эту точную последовательность полукокса \\1 поэтому не видит его как обратная ссылка, после изменений, внесенных в управляющие последовательности если таковые имеются.

  • В текстовом файле, а обратный слэш не интерпретируется, использование: <!-- start -->Replacement 2\\1<!-- end -->

  • В файле PHP кода, в кавычках строки в одного, \\ производит \ и \1 не меняется: использование '<!-- start -->Replacement 2\\\1<!-- end -->'

  • в файле PHP кода в кавычки строки в двойной, \\ производит \ и \1 рассматривается как восьмеричное полукокса: использовать '<!-- start -->Replacement 2\\\\1<!-- end -->'

Теперь вы привыкаете к обратному косой черте ...

Смежные вопросы