[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Баг preg_replace()?
Kiosuki
Есть такое выражение (для наглядности все упрощено):
echo preg_replace("/(\".*\")/e","'\\1'",'"1\"2"');

Что ожидается на консоли?
"1\"2"

А на самом деле выводится следующее:
\"1\\"2\"

Я где-то ошибаюсь? Как это побороть? Спасибо знатокам заранее.
P.S. На каком-то этапе к двойным кавычкам приклеивается бекслеш.



Спустя 7 минут, 44 секунды (23.09.2010 - 10:51) twin написал(а):
echo preg_replace("/".preg_quote('(\".*\")')."/e","'\\1'",'"1\"2"');

Спустя 4 часа, 40 минут, 57 секунд (23.09.2010 - 15:32) Kiosuki написал(а):
Цитата (twin @ 23.09.2010 - 07:51)
echo preg_replace("/".preg_quote('(\".*\")')."/e","'\\1'",'"1\"2"');

Да не... Спасибо, конечно, но что-то вы не то пишете. Вернее, совершенно не то. preg_quote() насколько я понимаю, нужен для форматирования строки под рег. выражение. А вы тут предлагаете само же выражение и форматировать. Кроме того, если проверить так (с применением вашего метода):
echo preg_replace("/".preg_quote("(\".*\")")."/e","'[\\1]'",'"1\"2"');
то ожидаемый вывод в виде:
["1\"2"]
не осуществляется. Здесь причина в другом. Или баг, или нужно какие-то флаги указать, или же строку как-то иначе передать. Вот я и спрашиваю, как решить эту задачу? Спасибо.

Спустя 32 минуты, 17 секунд (23.09.2010 - 16:04) SlavaFr написал(а):
ты не мог бы просто человеческом языком описать, что, где и при каких условиях ты своим регулярным выражением хочеш добится? для чего используется модификатор "е"?
[юмор]возможно ошибка находится не в preg_replace, a между монитором и креслом?[/юмор]

Спустя 10 минут, 22 секунды (23.09.2010 - 16:15) twin написал(а):
Ёмаё... прогнал конечно. Не туда подумал.
У тебя же там модификатор e стоит. Дык ты и пользуйся моментом
 echo preg_replace("/(\".*\")/e","stripslashes('[$1]');",'"1\"2"');

Спустя 26 минут, 13 секунд (23.09.2010 - 16:41) Kiosuki написал(а):
Ок, описываю задачу. Вцелом, она сложна. Но я выделил небольшой фрагмент. И так, необходимо открыть файл PHP, все строки, заключенные в двойные кавычки, заменить на константу, которая генерируется на основе md5.
Для простоты опустим, что в двойных кавычках могут находиться переменные, так же, опустим, что двойные кавычки могут пересекаться, например, с одинарными или комментариями, например:
/*"*/"

И так, регулярное выражение для строк в двойных кавычках (между двойными кавычками могут быть либо НЕ двойные кавычки, либо НЕ бэкслэш, либо бэкслэш, после которого может быть любой символ):
$DoubleQ='"(?:[^"\\]|\\.)*?"'

С помощью него мы будем вылавливать эти строки в двойных кавычках.
Соответственно, для замены во всем файле необходимо использовать:
$Content=preg_replace("/($DoubleQ)/msie","'_'.md5('\\1')",$Content);

Так вот, если мы имеем следующий фрагмент кода в обрабатываемом файле:
$A="1\"2";

То он должен быть заменен, по сути, на следующее:
$A=_CONSTANT1; /*_CONSTANT1=md5('"1\"2"')*/

А на самом деле заменяется не верно, на следующее:
$A=_CONSTANT2; /*_CONSTANT2=md5('\"1\\"2\"')*/

Где бок? Надеюсь, понятно выразился huh.gif

Спустя 16 минут, 12 секунд (23.09.2010 - 16:57) twin написал(а):
Никогда не имел дела с модификатором e...
Тут сама собой напрашивается preg_replace_callback();

Видимо функция перед исполнением экранирует спецсимволы. Это вообще то логично. Ну я же написал решение, хотя и черезпопное:
$Content = preg_replace("/($DoubleQ)/msie","'_'.md5(stripslashes('\\1'))",$Content);

Спустя 16 минут, 55 секунд (23.09.2010 - 17:14) Kiosuki написал(а):
Цитата (twin @ 23.09.2010 - 13:57)
Никогда не имел дела с модификатором e...
Тут сама собой напрашивается preg_replace_callback();

Видимо функция перед исполнением экранирует спецсимволы. Это вообще то логично. Ну я же написал решение, хотя и черезпопное:
$Content = preg_replace("/($DoubleQ)/msie","'_'.md5(stripslashes('\\1'))",$Content);

Обратите внимание, что если экранирование какое-то внутреннее и идет, то по логике и сам бэкслэш тоже должен быть отэкранирован, чего, увы, мы не наблюдаем. Посмотрите мой предыдущий пост, там видно, что бэкслэш не экранирован, иначе мы бы имели:
\"1\\\"2\"

В указанном мною выше случае, конечно, можно применить stripslashes(), но нельзя вот так вслепую применять первое попавшееся кажущееся решение, ибо я не понимаю, честно, механизма возникновения этих бэкслэшей перед двойными кавычками. Кроме того, не известно, перед какими символами могут эти дополнительные бэкслэши появляться и с какой стати? Вот я и спрашиваю, какое здесь верное решение?

Спустя 13 минут, 43 секунды (23.09.2010 - 17:28) Kiosuki написал(а):
Цитата (twin @ 23.09.2010 - 13:57)
Никогда не имел дела с модификатором e...
Тут сама собой напрашивается preg_replace_callback();

Видимо функция перед исполнением экранирует спецсимволы. Это вообще то логично. Ну я же написал решение, хотя и черезпопное:
$Content = preg_replace("/($DoubleQ)/msie","'_'.md5(stripslashes('\\1'))",$Content);

Как я и предполагал, не совсем ясна природа этого "внутреннего экранирования", ибо:

$S='"1\"\n2"';
echo preg_replace("/(\".*\")/e","'['.('\\1').']'",$S);
echo preg_replace("/(\".*\")/e","'['.stripslashes('\\1').']'",$S);

Выведет, соответственно:

[\"1\\"\n2\"]
["1\"n2"]

Символ новой строки превращается в n.
Все-таки, баг preg_replace()?

Спустя 3 часа, 43 секунды (23.09.2010 - 20:28) SlavaFr написал(а):
Цитата
Символ новой строки превращается в n.

символ новой стрички \n не превращался не когда в новую строчку, если его использовали в одинарных кавычках.
попробуй эти два варианта чтоб убедится

echo 'test\ntest';
echo "test\ntest";

Спустя 19 минут, 38 секунд (23.09.2010 - 20:48) twin написал(а):
Тут не в этом дело. Слэш все равно срезается. А не должен бы по идее.
То, что идет экранирование - вполне логично. А почему режется второй слой - пока не ясно. sad.gif Как то не так надо. Где то на поверхности ответ.

Спустя 17 минут, 40 секунд (23.09.2010 - 21:06) Kiosuki написал(а):
Цитата (SlavaFr @ 23.09.2010 - 17:28)
Цитата
Символ новой строки превращается в n.

символ новой стрички \n не превращался не когда в новую строчку, если его использовали в одинарных кавычках.
попробуй эти два варианта чтоб убедится

echo 'test\ntest';
echo "test\ntest";

Ты не вчитался в суть задачи. Просмотри еще раз внимательно, если тебе это интересно, прежде, чем постить лишь бы что. Для скрипта, который я рассматриваю, \n - это просто набор из двух символов. А переводом строки он является для скрипта, который парсится.

Спустя 2 минуты, 12 секунд (23.09.2010 - 21:08) Kiosuki написал(а):
Цитата (twin @ 23.09.2010 - 17:48)
Тут не в этом дело. Слэш все равно срезается. А не должен бы по идее.
То, что идет экранирование - вполне логично.  А почему режется второй слой - пока не ясно.  sad.gif  Как то не так надо. Где то на поверхности ответ.

То-то и оно... Я в php.net написал в баг-репорт. Может, опять-таки, я чего-то не понимаю, где тут бочина, но явно что-то не в порядке.

Спустя 2 часа, 18 минут, 27 секунд (23.09.2010 - 23:26) SlavaFr написал(а):
да, увидел, действительно глючат "\" перед кавычками при использовании модифера "е".
в последнем примере не должно было остатся "\".

прейдется с preg_replace_callback работать.

Спустя 12 часов, 56 минут, 51 секунда (24.09.2010 - 12:23) Kiosuki написал(а):
Уважаемые знатоки, ответ, оказывается, действительно был на поверхности:
http://bugs.php.net/bug.php?id=52914&edit=2
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.