Роман К.
6970 повідомлень
#15 років тому
Не могу понять. Помогите, плз.

Есть скрипт, заменяющий ссылки в тексте на теги a href.
Исходный текст: (Сайт)
Текст после замены: <a href=http://site.com>Сайт</a>

Замена проводится вот этим кодом:
eregi("((http:)]+) \((.+)\)", $article_in, $url);
if ($url<>"") $article_in=eregi_replace("((http:)]+) \((.+)\)", "<a href=".$url.">".$url."</a> ", $article_in);


Проблема в этой части регулярного выражения:
\((.+)\)
Вроде как оно должно означать "открывающаяся скобка плюс любое количество любых символов плюс закрывающаяся скобка). Но почему-то первая закрывающаяся скобка игнорируется и текст берётся до последней закрывающейся скобки в строке. В доступных мне справочниках по PHP этой оговорки не нашёл.
Что я делаю не так?
Евгений О.
2989 повідомлень
#15 років тому
Попробуйте заменить .+ на .*? или (.+) на (.+)?
Если не поможет можно попробовать вот так
"((http:)]+) \((.+)\)"

p.s. Вам надо избавиться от "жадности" обработчика регулярного выражения
Роман К.
6970 повідомлень
#15 років тому
Цитата ("elosoft"):
Попробуйте заменить .+ на .*?

Выдает ошибку.

Цитата:
или (.+) на (.+)?

Тот же результат, что и с моим выражением.

Цитата:
Если не поможет можно попробовать вот так
"((http:)]+) \((.+)\)"

Тут воообще фигня получается: он проглатывает последний символ строки. И всё равно проскакивает первую скобку.

Цитата:
p.s. Вам надо избавиться от "жадности" обработчика регулярного выражения

Вот я и не могу понять, как... Есть, конечно, лобовой способ - прописать все возможные символы, но... неаккуратно как-то.

Главное ведь - стабильно идёт от текущей открывающейся скобки до последней закрывающейся в строке. Соответственно, если пара скобок одна - срабатывает нормально.
И ещё. Если поставить перед закрывающейся кавычкой пробел (т.е. паттерн заканчивается комбинацией "скобка пробел", то срабатывает нормально. Но - уже не срабатывает, когда весь абзац - ссылка, т.е. пробела после скобки нет.
Роман К.
6970 повідомлень
#15 років тому
Оффтопик
Пока проблему решил вставкой пробелов после закрывающейся скобки. Но решение не нравится, поэтому вопрос - в силе.

Upd. Фиг там, не решил. Пробел после скобки ставить нельзя, потому что он убирается в результате работы другой функции. Вопрос - тем более в силе.
Евгений О.
2989 повідомлень
#15 років тому
Обработчики для ускорения всегда стараются захвать сразу максимально большой кусок. У Вас это будет от первой подпавшей под выражение открывающей скобки до последней.
zzzzzzzzzzzzzzz http:zzzz(первое попавшее) zzzzzzzzz http:zzzz(последнее поппавшее)

получим
первое попавшее) zzzzzzzzz http:zzzz(последнее поппавшее)

Это и есть жадность.
От жадности можно избавить использую знак вопроса или заблокировать повторение каких-то элементов. Ваш запрос я бы начал писать так
"((http:)]+) \((\w+)\)"

А дальше по обстоятельствам...

вот здесь есть хорошие примеры
Роман В.
99 повідомлень
#15 років тому
Можно поробовать так:

"(http:]+) \((*)\)"


т.е. исключить из множества скобку.
Сергей Ф.
15 повідомлень
#15 років тому
Как вариант - можно использовать рекурсивные выражения

$text = 'Исходный текст:  (Просто текст (описание ссылки (3 (4 текст!))))';
echo preg_replace('#(http://]++) (\(((?:++|(?2))*)\))#i', '<a href="$1">$3</a>', $text);
Роман К.
6970 повідомлень
#15 років тому
Цитата ("ferggren"):
Как вариант - можно использовать рекурсивные выражения

Японский магнитофон!
Оно работает, конечно... а проще это никак не реализовать?
Сергей Ф.
15 повідомлень
#15 років тому
Если вложенных скобок нет, то можно использовать простой вариант:
$text = ' (Сайт 1)  (Сайт 2)  (Сайт ($!4))';
echo preg_replace('#(http://]++) \((++)\)#is', '<a href="$1">$2</a>', $text);
Роман К.
6970 повідомлень
#15 років тому
Попробовал вот такое выражение

\((.*?)\)


Вроде как символ ? должен отключить жадность. Но получается ошибка REG_BADRPT.
Вадим Т.
3240 повідомлень
#15 років тому
Цитата ("voron_76"):
Вроде как символ ? должен отключить жадность. Но получается ошибка REG_BADRPT.

POSIX функции для работы с регекспами не поддерживают такую возможность. Поэтому лучше используйте функции PCRE, которые поддерживают.
Выше как раз посоветовали вариант с preg_replace (PCRE), а Вы, вероятно, сейчас по-прежнему пробуете вариант с eregi (про который лучше забыть, как про страшный сон, тем более что в PHP 5.3 оно уже объявлено как deprecated, а из PHP 6 вообще будет удалено как мусор).
Роман К.
6970 повідомлень
#15 років тому
Цитата ("tvv"):
Цитата ("voron_76"):
Вроде как символ ? должен отключить жадность. Но получается ошибка REG_BADRPT.

POSIX функции для работы с регекспами не поддерживают такую возможность. Поэтому лучше используйте функции PCRE, которые поддерживают.
Выше как раз посоветовали вариант с preg_replace (PCRE), а Вы, вероятно, сейчас по-прежнему пробуете вариант с eregi (про который лучше забыть, как про страшный сон, тем более что в PHP 5.3 оно уже объявлено как deprecated, а из PHP 6 вообще будет удалено как мусор).

Понял. Спасибо.
Роман К.
6970 повідомлень
#15 років тому
Вот что получилось в итоге.
Скрипт, заменяющий в текстовом файле комбинации вида "http://site.com (сайт)" на ссылку.

<?
$article_in=file("1.txt");

for($i=0; $i < count($article_in); $i++)
{
$url="";
preg_match("/((http:)]+) \((.+?)\)/", $article_in, $url);
if ($url<>"") $article_in=preg_replace("/((http:)]+) \((.+?)\)/", "<a href=".$url.">".$url."</a> ", $article_in);
echo($article_in."<br>");

}

?>
Роман Беляев
16382 повідомлення
#15 років тому
Цитата ("voron_76"):
Вот что получилось в итоге.


Костыль это все. Ссылки должны быть ссылками. Захочется проставить target ссылке или class причепить и все. А для такой вот замены есть bbcode
Роман К.
6970 повідомлень
#15 років тому
Цитата ("frig"):
Цитата ("voron_76"):
Вот что получилось в итоге.

Костыль это все. Ссылки должны быть ссылками. Захочется проставить target ссылке или class причепить и все. А для такой вот замены есть bbcode

Это не костыль, это решение конкретной задачи. А bbcode вручную вставлять неудобно. К тому же, принципиальной разницы, для чего делать обработчик - для bbcode или для такой вот конструкции - по-моему, нет.
Роман Беляев
16382 повідомлення
#15 років тому
Цитата ("voron_76"):
К тому же, принципиальной разницы, для чего делать обработчик - для bbcode или для такой вот конструкции - по-моему, нет.


Ну почему же? Обработчик для bbcode надо просто готовый взять. Кстати можно и просто поставить WYSIWYG редактор на веб страницу и вообще рулить как вордом.

костыль :P
Роман К.
6970 повідомлень
#15 років тому
Цитата ("frig"):
Цитата ("voron_76"):
К тому же, принципиальной разницы, для чего делать обработчик - для bbcode или для такой вот конструкции - по-моему, нет.

Ну почему же? Обработчик для bbcode надо просто готовый взять.

И разбираться, каким местом его прикручивать. Ну нафиг. Я не настолько хорошо PHP знаю, мне проще самому написать. Опять же - вставлять руками их всё равно неудобно.

Цитата:
Кстати можно и просто поставить WYSIWYG редактор на веб страницу и вообще рулить как вордом.

Бр-р... У меня был как-то набор макросов для Ворда, которые расставляли HTML-теги в текстовом файле - по сути, тот же WYSIWYG-редактор. Но ведь это же надо ручками всё расставлять. А зачем расставлять ручками, если можно нажать кнопку и всё сделается само? :P

Цитата:
костыль :P

И вообще - не костыль, а учебный полигон. :P
Роман Беляев
16382 повідомлення
#15 років тому
Цитата ("voron_76"):
И вообще - не костыль, а учебный полигон.


А я вот не спорю на счет учебного полигона. Одно другому не мешает. Учебный полигон, а на нем костыль. Как для учебного полигона - полезно. Но все равно костыль.

Цитата ("voron_76"):
И разбираться, каким местом его прикручивать. Ну нафиг.


Там мануалы есть...
Роман К.
6970 повідомлень
#15 років тому
Цитата ("frig"):
Цитата ("voron_76"):
И вообще - не костыль, а учебный полигон.

А я вот не спорю на счет учебного полигона. Одно другому не мешает. Учебный полигон, а на нем костыль. Как для учебного полигона - полезно. Но все равно костыль.

Это, кстати, не самостоятельный продукт, а часть обработчика, подготавливающего текстовый файл для заливки на страницу. Там только 6, 7 и 8 строчки нужны, они пойдут в основной обработчик. Всё остальное - обрамление для отладки.
А если надо будет какие-то дополнительные параметры к ссылкам прикрутить - я просто ещё условий допишу.
Роман Беляев
16382 повідомлення
#15 років тому
Начинать с написания своего шаблонизатора - более чем оригинально, на мой взгляд.