PHP: поиск, замена, сокращение и предварительная обработка пользовательских ссылок тегами <a>, эллипсами и значками ссылок - PullRequest
0 голосов
/ 04 ноября 2010

Когда пользователь вводит URL, например, http://www.google.com, я хотел бы иметь возможность проанализировать этот текст с помощью PHP , , найти любые ссылки , и заменить их с <a> тегами, которые включают исходный URL в виде HREF.

Другими словами, http://www.google.com станет

<a href="http://www.google.com">http://www.google.com</a>

IВы хотели бы иметь возможность сделать это для всех URL-адресов этих форм (с .com взаимозаменяемыми с любым TLD):

http://www.google.com
www.google.com
google.com
docs.google.com

Какой самый эффективный способ сделать это?Я мог бы попытаться написать какое-нибудь действительно необычное регулярное выражение, но я сомневаюсь, что это лучший метод, доступный для меня.

Для бонусных баллов я также хотел бы добавить http:// к любому URL, в котором его нет, и убрать показотправьте текст в виде http://www.google.com/reallyLongL... и затем отобразите значок внешней ссылки.

Ответы [ 6 ]

1 голос
/ 04 ноября 2010

Очиститель HTML имеет встроенную функцию линковки , чтобы избавить вас от головной боли.

Это другие функции, которые просто слишком полезны, чтобы их упустить, если вы имеете дело с любым видом пользовательского ввода, который вам также нужно отобразить.

1 голос
/ 04 ноября 2010

www.google.com

Это не URL, это имя хоста. Как правило, не стоит начинать разметку пустых имен хостов в произвольном тексте, поскольку в общем случае любое слово или последовательность слов, разделенных точками, является совершенно допустимым именем хоста. Это означает, что вы столкнулись с ужасными взломами, такими как поиск ведущих www. (и у вас возникнут вопросы типа «почему я могу ссылаться на www.stackoverflow.com, но не stackoverflow.com?») Или конечные TLD (что становится все более и более непрактичным по вводится больше новых TLD: «почему я могу любить ncm.com, но не ncm.museum?»), и вы будете часто отмечать вещи, которые не должны быть ссылками.

Я мог бы попытаться написать какое-нибудь действительно необычное регулярное выражение

Ну, я не понимаю, как бы вы это сделали без регулярное выражение.

Трюк справляется с разметкой. Если на входе могут быть символы <, & и ", вы не должны допускать их к выводу HTML. Если вы вводите простой текст, вы можете сделать это, позвонив по номеру htmlspecialchars(), прежде чем применить простую замену к шаблону, подобному тому, что был в ответе Нико.

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

Другая проблема - конечная пунктуация. Обычно люди ставят после ссылки точку, запятую, закрывающую скобку, восклицательный знак и т. Д., Которые не должны быть частью ссылки, но на самом деле являются действительными символами. Это полезно, чтобы удалить их и не помещать их в ссылку. Но затем вы разрываете ссылки на вики, оканчивающиеся на ), поэтому, возможно, вы не захотите трактовать ) как завершающий символ, если в ссылке есть (, или что-то в этом роде. Такого рода вещи нельзя сделать с помощью простой замены регулярных выражений, но вы можете сделать это с помощью функции обратного вызова замены.

1 голос
/ 04 ноября 2010

Попытка найти ссылки в формате domain.com будет проблемой в задницу. Для этого потребуется отслеживать все TLD и использовать их в поиске. Если вы не указали конец последнего напечатанного мной предложения, а в начале этого предложения будет ссылка на http://search.if. Даже если вы это сделали. действительный домен верхнего уровня и общее слово.

Я бы порекомендовал сообщить своим пользователям, что они должны начинать ссылки с www. или http://, а затем написать простое регулярное выражение для захвата их и добавления ссылок.

0 голосов
/ 04 ноября 2010

С http://www.exorithm.com/algorithm/view/markup_urls

function markup_urls ($text)
{
  // split the text into words
  $words = preg_split('/([\s\n\r]+)/', $text, -1, PREG_SPLIT_DELIM_CAPTURE);
  $text = "";

  // iterate through the words
  foreach($words as $word) {

    // chopword = the portion of the word that will be replaced
    $chopword = $word;
    $chopword = preg_replace('/^[^A-Za-z0-9]*/', '', $chopword);

    if ($chopword <> '') {
      // linkword = the text that will replace chopword in the word
      $linkword='';

      // does it start with http://abc. ?
      if (preg_match('/^(http:\/\/)[a-zA-Z0-9_]{2,}.*/', $chopword)) {

        $chopword = preg_replace('/[^A-Za-z0-9\/]*$/', '', $chopword);
        $linkword = '<a href="'.$chopword.'" target="blank">'.$chopword.'</a>';

      // does it equal abc.def.ghi ?
      } else if (preg_match('/^[a-zA-Z]{2,}\.([a-zA-Z0-9_]+\.)+[a-zA-Z]{2,}(\/.*)?/', $chopword)) {

        $chopword = preg_replace('/[^A-Za-z0-9\/]*$/', '', $chopword);
        $linkword = '<a href="http://'.$chopword.'" target="blank">'.$chopword.'</a>';

      // does it start with abc@def.ghi ?
      } else if (preg_match('/^[a-zA-Z0-9_\.]+\@([a-zA-Z0-9_]{2,}\.)+[a-zA-Z]{2,}.*/', $chopword)) {

        $chopword = preg_replace('/[^A-Za-z0-9]*$/', '', $chopword);
        $linkword = '<a href="mailto:'.$chopword.'">'.$chopword.'</a>';

      }

      // replace chopword with linkword in word (if linkword was set)
      if ($linkword <> '') {
        $word = str_replace($chopword, $linkword, $word);
      }
    }

    // append the word
    $text = $text.$word;
  }

  return $text;
} 
0 голосов
/ 04 ноября 2010

Я получил это работает именно так, как я хочу здесь:

<?php

$input = <<<EOF
http://www.example.com/
http://example.com
www.example.com
http://iamanextremely.com/long/link/so/I/will/be/trimmed/down/a/bit/so/i/dont/mess
/up/text/wrapping.html
EOF;

  function trimlong($match)
  {
    $url = $match[0];
    $display = $url;
    if ( strlen($display) > 30 ) {
      $display = substr($display,0,30)."...";
    }
    return '<a href="'.$url.'">'.$display.' <img src="http://static.goalscdn.com/img/external-link.gif" height="10" width="11" /></a>';
  }

$output = preg_replace_callback('#(http://|www\\.)[^\\s<]+[^\\s<,.]#i',
                                 array($this,'trimlong'),$input);

echo $output;
0 голосов
/ 04 ноября 2010

Не так уж необычные регулярные выражения, которые должны работать

/\b(https?:\/\/[^\s+\"\<\>]+)/ig
/\b(www.[^\s+\"\<\>]+)/ig

Обратите внимание, что последние два будет невозможно сделать правильно, поскольку вы не можете отличить google.com от чего-то подобного. Где я заканчиваю одно предложение и не ставлю пробел после полной остановки.

Что касается сокращения URL-адресов, указав ваш URL-адрес в $url:

if (strlen($url) > 20) // Or whatever length you like
   {
   $shortURL = substr($url, 0, 20)."&hellip;";
   }
else
   {
   $shortURL = $url;
   }

echo '<a href="'.$url.'" >'.$shortURL.'</a>';
...