Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / (php) замена текста, пропуская html-мнемоники / 25 сообщений из 47, страница 1 из 2
29.07.2014, 20:20
    #38708536
Cyrax_02
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(php) замена текста, пропуская html-мнемоники
Например, имеется html-текст:
Код: html
1.
0&1;2;3

который при отображении страницы выглядит так:
0&1;2;3

В этом html-тексте точку с запятой нужно заменить переходом на новую строку:
Код: html
1.
0&amp;1<br/>2<br/>3

и будет выглядеть это так:
0&1
2
3

Задача простая ? На первый взгляд.
Вручную парсить html-мнемоники не хочется. Можно ли решить задачу как-нибудь попроще ? Без ручного парсинга ?

Пару html_entity_decode / htmlentities использовать не получится, поскольку htmlentities у фрагмента '<br/>' заменит угловые скобки на html-сущности и в результате вместо перехода на новую строку мы получим строку '<br/>':
0&1<br/>2<br/>3
...
Рейтинг: 0 / 0
29.07.2014, 23:02
    #38708602
vkle
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(php) замена текста, пропуская html-мнемоники
Cyrax_02Пару html_entity_decode / htmlentities использовать не получится, поскольку htmlentities у фрагмента '<br/>' заменит угловые скобки на html-сущностиЭто было решение задачи в лоб. Думаю, можно сделать промежуточную замену, на что-то вроде '[br]', а затем, после обратного преобразования в сущности, заменить этот текст на требуемый.

Еще можно посмотреть в сторону регулярных выражений.
...
Рейтинг: 0 / 0
30.07.2014, 10:01
    #38708745
Cyrax_02
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(php) замена текста, пропуская html-мнемоники
авторДумаю, можно сделать промежуточную замену, на что-то вроде '[br]', а затем, после обратного преобразования в сущности, заменить этот текст на требуемый.
Вместо '<br/>' может быть любой текст, содержащий любые теги. Нужно общее решение.
Да, можно во фрагменте, на который происходит замена (в сабжевом примере - '<br/>'), заменять все угловые скобки на некоторые комбинации, которые в html-тексте заведомо не встречаются (самый простой вариант - '[' и ']'), а в конце - их восстанавливать.

Но здесь есть 2 проблемы:
1. Комбинации, которые в html-тексте заведомо не встречаются , когда-нибудь могут встретиться.
2. После выполнения всех процедур в html-тексте железно все символы (имеющие html-мнемоники) будут заменены на эти самые html-мнемоники. А желательно сохранить исходную картину - так как было в самом начале (какие-то символы - в виде символов, какие-то - в виде html-мнемоник).
Т.е. данная процедура не должна производить никаких иных (побочных) манипуляций с html-строкой, кроме целевой замены (целевой задачи). Это одно из правил хорошего тона в программировании.
...
Рейтинг: 0 / 0
30.07.2014, 10:03
    #38708747
Cyrax_02
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(php) замена текста, пропуская html-мнемоники
Очень странно, что таком мощном языке как php не предусмотрено функций замены подстроки с исключением из поиска некоторых фрагментов (задаваемых, например, регуляркой).
...
Рейтинг: 0 / 0
30.07.2014, 12:11
    #38708951
ScareCrow
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(php) замена текста, пропуская html-мнемоники
Cyrax_02Очень странно, что таком мощном языке как php не предусмотрено функций замены подстроки с исключением из поиска некоторых фрагментов (задаваемых, например, регуляркой).

то что вы их не знаете, не значит то их нет.
...
Рейтинг: 0 / 0
30.07.2014, 14:08
    #38709092
Cyrax_02
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(php) замена текста, пропуская html-мнемоники
А, ясно. Это т.н. скрытые функции php . Доступ только по паролю.
...
Рейтинг: 0 / 0
30.07.2014, 14:56
    #38709139
ScareCrow
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(php) замена текста, пропуская html-мнемоники
...
Рейтинг: 0 / 0
30.07.2014, 15:58
    #38709218
Cyrax_02
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(php) замена текста, пропуская html-мнемоники
ScareCrow https://php.net/manual/ru/function.preg-replace-callback.php Ну и каким образом Вы предполагаете внутри callback-функции определять, переданный ей фрагмент извлечён из html-сущности или нет ? (в первом случае замена выполняться НЕ должна, во втором случае - должна)

Внутри callback-функции контекст передаваемого ей фрагмента неизвестен.
...
Рейтинг: 0 / 0
30.07.2014, 17:12
    #38709296
ScareCrow
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(php) замена текста, пропуская html-мнемоники
как хотите.
...
Рейтинг: 0 / 0
30.07.2014, 18:32
    #38709391
Cyrax_02
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(php) замена текста, пропуская html-мнемоники
Вообще-то, из того, что я описал, следует абсолютная бесполезность предложенной Вами функции preg_replace_callback() в решении сабжевой задачи.
...
Рейтинг: 0 / 0
30.07.2014, 18:34
    #38709394
Cyrax_02
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(php) замена текста, пропуская html-мнемоники
...а также голословность утверждения:
то что вы их не знаете, не значит то их нет.
...
Рейтинг: 0 / 0
30.07.2014, 23:11
    #38709566
Програмёр
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(php) замена текста, пропуская html-мнемоники
Cyrax_02,

ну вообще ScareCrow вроде прав в плане preg_replace_callback (если я верно понял).
можно составить регулярку как-то так: "/(&(#\d+|\w+))?;/"
это позволит выловить все ";", а также всё, что потенциально является &-последовательностью.
ну а в callback-е делать htmlspecialchars_decode выловленного участка, и если он не изменился, значит мы нашли не сущность и потому спокойно можем заменить ";" на "<br>"

В общем как-то так :)
...
Рейтинг: 0 / 0
31.07.2014, 10:14
    #38709745
Cyrax_02
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(php) замена текста, пропуская html-мнемоники
авторможно составить регулярку как-то так: "/(&(#\d+|\w+))?;/"
это позволит выловить все ";", а также всё, что потенциально является &-последовательностью.
ну а в callback-е делать htmlspecialchars_decode выловленного участка, и если он не изменился, значит мы нашли не сущность и потому спокойно можем заменить ";" на "<br>"Опять мимо:
1. htmlspecialchars_decode , htmlentities и html_entity_decode НЕ работают с кодами символов вида xxx;
2. Почему Вы зацикливаетесь на частностях ? Сегодня нужно найти заменить точку с запятой, завтра - амперсанд, а послезавтра - двузначное число.

После прочтения конкретного примера из 1-го поста, я так думаю, должна была решаться такая задача:
В строке str на подстроку substr2 необходимо заменить все подстроки substr1 , которые не входят в состав подстроки pass , задаваемой регулярным выражением.

P.S. Когда нам требуется написать парсер арифметического выражения 2+2, мы ведь не пишем парсер, который понимает только это выражение - мы пишем парсер, который работает с любым арифметическим выражением. Это же логично.
...
Рейтинг: 0 / 0
31.07.2014, 13:06
    #38709961
?
?
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(php) замена текста, пропуская html-мнемоники
Cyrax_02В строке str на подстроку substr2 необходимо заменить все подстроки substr1 , которые не входят в состав подстроки pass , задаваемой регулярным выражением.
preg_split с флагом PREG_SPLIT_DELIM_CAPTURE + preg_replace + implode.
Но вообще-то первоначальная постановка вызывает много вопросов, например - а надо ли делать замены в значениях атрибутов в htlm тегах? А во встроенных таблицах стилей / javascript? А html-entity достаточно просто проверять по регулярному выражению, или нужно учитывать только реально существующие?
...
Рейтинг: 0 / 0
31.07.2014, 18:49
    #38710320
Cyrax_02
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(php) замена текста, пропуская html-мнемоники
авторpreg_split с флагом PREG_SPLIT_DELIM_CAPTURE + preg_replace + implode.Такой вариант я уже реализовал (правда, вместо preg_split + PREG_SPLIT_DELIM_CAPTURE использовал preg_replace + explode ). По скорости вариант неприемлем. Потому что для каждого полученного фрагмента снова вызывается обработчик регулярок.
А обработчик регулярок должен быть вызван всего 1 раз - для разбития строки на подстроки по шаблону. Далее уже регулярки не трогаем. Такой вариант, думаю, реализуем с помощью preg_split + PREG_SPLIT_OFFSET_CAPTURE . Сейчас состряпаю...
...
Рейтинг: 0 / 0
31.07.2014, 19:34
    #38710343
Cyrax_02
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(php) замена текста, пропуская html-мнемоники
авторА обработчик регулярок должен быть вызван всего 1 раз - для разбития строки на подстроки по шаблону. Далее уже регулярки не трогаем. Такой вариант, думаю, реализуем с помощью preg_split + PREG_SPLIT_OFFSET_CAPTURE.Всё так и есть. Этот вариант работает в несколько раз быстрее:

Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
function func_strReplaceWithExclusion($str, $substr1, $substr2, $pass = '') {
    $encoding = ...
        
    $output = '';
    if($pass == '') {
        $output = str_replace($substr1, $substr2, $str);
        
    } else {    
        if(preg_match($str, '') === false) { $pass = '/'.preg_quote($pass, '/').'/'; }
        $strParts = preg_split($pass, $str, -1, PREG_SPLIT_OFFSET_CAPTURE);
            
        $pos = 0;
        foreach($strParts as $part) {
            $output .= mb_substr($str, $pos, $part[1] - $pos, $encoding);
            $output .= str_replace($substr1, $substr2, $part[0]);
            $pos = $part[1] + mb_strlen($part[0], $encoding);
        }
    }
    return $output;
}


По скорости - вполне приемлем.
...
Рейтинг: 0 / 0
31.07.2014, 20:00
    #38710351
Cyrax_02
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(php) замена текста, пропуская html-мнемоники
Только вот здесь
Код: php
1.
if(preg_match($str, '') === false) {...}

перед preg_match нужно поставить @
...
Рейтинг: 0 / 0
31.07.2014, 22:48
    #38710424
Програмёр
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(php) замена текста, пропуская html-мнемоники
Cyrax_02 P.S. Когда нам требуется написать парсер арифметического выражения 2+2, мы ведь не пишем парсер, который понимает только это выражение - мы пишем парсер, который работает с любым арифметическим выражением. Это же логично.

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

Иначе смысл в таком фейерверке и в такой рогатке?
Ну думаю продолжать обсуждать задачу смысла нету, так как оказалось, что перед Вами стоит совсем не та задача, которую Вы описали.

авторВ строке str на подстроку substr2 необходимо заменить все подстроки substr1, которые не входят в состав подстроки pass, задаваемой регулярным выражением.

Код: php
1.
$res = str_replace(array("/$pass/", "/$substr1/"), array("\0", $substr2), $str);



Только вот поставленная задача далека от первой, и соответственно решение к этой задаче не подойдёт для озвученной изначально. Или ставьте нормальную задачу... или закрывайте тему (а то Вам отвечают, а Вы тут аналогии непонятные приводите... типа поставили задачу, но решать надо не её, а некую сферическую в вакууме).
...
Рейтинг: 0 / 0
01.08.2014, 10:42
    #38710583
vkle
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(php) замена текста, пропуская html-мнемоники
Cyrax_02перед preg_match нужно поставить @Зачем?
...
Рейтинг: 0 / 0
01.08.2014, 11:53
    #38710667
Cyrax_02
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(php) замена текста, пропуская html-мнемоники
vkleCyrax_02перед preg_match нужно поставить @Зачем?
Чтобы не засорять логи.
...
Рейтинг: 0 / 0
01.08.2014, 12:20
    #38710701
Cyrax_02
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(php) замена текста, пропуская html-мнемоники
ПрограмёравторВ строке str на подстроку substr2 необходимо заменить все подстроки substr1, которые не входят в состав подстроки pass, задаваемой регулярным выражением.
Код: php
1.
$res = str_replace(array("/$pass/", "/$substr1/"), array("\0", $substr2), $str);


Даже если предположить, что вместо str_replace Вы хотели написать preg_replace , то Ваш вариант всё-равно остаётся неработоспособным - в результирующей строке мы потеряем все фрагменты, соответствующие шаблону $pass.
...
Рейтинг: 0 / 0
01.08.2014, 12:26
    #38710708
Cyrax_02
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(php) замена текста, пропуская html-мнемоники
ПрограмёрТолько вот поставленная задача далека от первой, и соответственно решение к этой задаче не подойдёт для озвученной изначально. Или ставьте нормальную задачу... или закрывайте тему (а то Вам отвечают, а Вы тут аналогии непонятные приводите... типа поставили задачу, но решать надо не её, а некую сферическую в вакууме).
Вы сильно удивитесь, но решение задачи, которую выполняет функция func_strReplaceWithExclusion() - это и есть прямое и полное решение сабжевой задачи:
Код: php
1.
2.
3.
4.
5.
$str = '<span>0&amp;1;2;3/4/5</span>';
$substr1 = array('/', ';');
$substr2 = '<br/>';
$pass = '/(?:<[^<>]+>)|(?:\&\#?\w+;)/';  // в составе тегов и html-сущностей замена не производится
$output = func_strReplaceWithExclusion($str, $substr1, $substr2, $pass)

Получаем:
Код: html
1.
<span>0&amp;1<br/>2<br/>3<br/>4<br/>5</span>


Если же что-то нужно заменить в составе тегов, то делаем так (используем ретроспективную позитивную проверку):
Код: php
1.
2.
$pass = '/(?:(?<=(?:^)|>)[^<>]+)|(?:\&\#?\w+;)/'  // в составе НЕтегов и html-сущностей замена не производится
$output = func_strReplaceWithExclusion($str, $substr1, $substr2, $pass)


P.S. Надеюсь, сферические кони в вакууме Вас больше не беспокоят ?
...
Рейтинг: 0 / 0
01.08.2014, 15:32
    #38710978
Програмёр
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(php) замена текста, пропуская html-мнемоники
Cyrax_02Програмёрпропущено...
Код: php
1.
$res = str_replace(array("/$pass/", "/$substr1/"), array("\0", $substr2), $str);


Даже если предположить, что вместо str_replace Вы хотели написать preg_replace , то Ваш вариант всё-равно остаётся неработоспособным - в результирующей строке мы потеряем все фрагменты, соответствующие шаблону $pass.

да... ошибся... думал через str_replace делать... потом понял что не получится и переписал на preg_replace.... только вот перепечатать префикс забыл ))

А если сделать:
Код: php
1.
$res = preg_replace(array("/$pass/", "/$substr1/"), array("\0", $substr2), $str);


то ничего не потеряется (тут Вы ошиблись)... первый шаблон заменится сам на себя, а второй - на то что нужно :)
...
Рейтинг: 0 / 0
01.08.2014, 15:55
    #38711015
Програмёр
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(php) замена текста, пропуская html-мнемоники
Cyrax_02ПрограмёрТолько вот поставленная задача далека от первой, и соответственно решение к этой задаче не подойдёт для озвученной изначально. Или ставьте нормальную задачу... или закрывайте тему (а то Вам отвечают, а Вы тут аналогии непонятные приводите... типа поставили задачу, но решать надо не её, а некую сферическую в вакууме).
Вы сильно удивитесь, но решение задачи, которую выполняет функция func_strReplaceWithExclusion() - это и есть прямое и полное решение сабжевой задачи:
Код: php
1.
2.
3.
4.
5.
$str = '<span>0&amp;1;2;3/4/5</span>';
$substr1 = array('/', ';');
$substr2 = '<br/>';
$pass = '/(?:<[^<>]+>)|(?:\&\#?\w+;)/';  // в составе тегов и html-сущностей замена не производится
$output = func_strReplaceWithExclusion($str, $substr1, $substr2, $pass)

Получаем:
Код: html
1.
<span>0&amp;1<br/>2<br/>3<br/>4<br/>5</span>




Нет ))) не всё что имеет формат "&\w+;" является &-последовательностью. Как пример - &nbsp; и &nbps; Первая заменяется на пробел, а вторая не заменяется ни на что и не пропадает. Потому то я и сказал, что начальную задачу так не решить (без использования htmlspecialchars_decode или вбивания всех возможных мнемоник) :) А что Вы за лисапед намутили - вообще не понятно... решается одной строкой (как я написал, или просто регуляркой с использованием шаблона отрицательного просмотра назад (вроде так зовётся) )

P.S. Но как говорит мой бывший напарник - "тебе из погреба виднее". Просили подсказать - подсказали... а уж если свой вариант нравится больше, так никто же спорить не будет. Но если Ваш проект кому достанется... - я бы за такой код явно не поблагодарил :)
...
Рейтинг: 0 / 0
01.08.2014, 17:36
    #38711153
Cyrax_02
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(php) замена текста, пропуская html-мнемоники
ПрограмёрА если сделать:
Код: php
1.
$res = preg_replace(array("/$pass/", "/$substr1/"), array("\0", $substr2), $str);


то ничего не потеряется (тут Вы ошиблись)...Нет, я прав. Проверьте - и убедитесь, что строка $pass "теряется".
А после того, как проверите, Вам станет ясно, что вместо "\0" нужно было писать '\0' или '$0'. Это Ваша 2-я ошибка .

авторпервый шаблон заменится сам на себя, а второй - на то что нужно :)Да, второй шаблон заменится на то, что нужно, но не там, где нужно . Второй шаблон будет заменён и в том, фрагменте, который соответствует 1-му шаблону (во втором проходе). Т.е. точка с запятой будет заменена и в составе html-сущностей.
Это Ваша 3-я ошибка.
...
Рейтинг: 0 / 0
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / (php) замена текста, пропуская html-мнемоники / 25 сообщений из 47, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]