2015-11-21 3 views
2

Я внедряю систему временных линий на своем веб-сайте, где пользователи могут указать других пользователей на их временной шкале, используя @username как твиттер.php regex - Замените все @usernames ссылкой в ​​строке

Я хочу, чтобы преобразовать @Username по ссылке и указать его на свой профиль

Моя строка:

$timeline="@fred-ii 's posts on @stackoverflow are intresting."; 

Я использую следующий код, чтобы заменить @Username с URL:

echo preg_replace("/@([^\s]+)/i","<a href='http://example.com/$1'>@$1</a>",$timeline); 

это работает, проблема в том, что он соответствует местам также

эта строка

"@fred-ii 's posts [email protected]"; 

Там нет места между на и @stackoverflow, я хочу, чтобы исключить его,

так я обновил мой регулярное выражение

/\[email protected]([^\s]+)/ 

он работал, но он не соответствовал первой части моей строки (имя пользователя @ fred-ii). Я думаю, что regex engine is looki ng для пробела | s в начале строки.

Что мне нужно изменить в моем шаблоне, чтобы соответствовать всем @usernames?

$timeline="@fred-ii 's posts on @stackoverflow are intresting."; 
+0

Таким образом, вы хотите, чтобы соответствовать пространство в имени пользователя, но не имеют места в ссылке? – Shomz

ответ

1

Вы можете использовать это утверждение с просмотром назад:

/(?<=\s|^)@\S+/ 

(?<=\s|^) убеждается есть пробелы или линии старта до того @.

Код:

php> $s = "@fred-ii 's posts [email protected]"; 

php> echo preg_replace('/(?<=\s|^)@\S+/', "<a href='http://example.com/$0'>$0</a>", $s); 
<a href='http://example.com/fred-ii'>@fred-ii</a> 's posts [email protected] 
+0

Анубхава: ваш ответ правильный, он дает выход из корректа.но что, если я не использую ** lookbehind **, например, шаблон **/(\ s + | ^) @ ([^ \ s] +)/** также работает, правильно ли использовать его или всегда с lookbehind. пожалуйста, направляйте меня. – starkeen

+1

Да, вы также можете использовать: '/ (?: \ S | ^) @ ([^ \ s] +) /' с захваченной группой. Lookbehind дает вам возможность вообще не использовать какую-либо захваченную группу: ** 'preg_replace ('/ (? <= \ S | ^) @ \ S + /'," $0 ", $ s);' ** – anubhava

+1

[ Спасибо] (https://eval.in/473806) так много для объяснения Анубхавы, я много узнал о LookBehind из вашего ответа и комментария. Я действительно предлагаю это. – starkeen

1

Вы можете сделать это с lookbehind negative assertion:

/(?<!\w)@([^\s]+)/ 

(?<!\w) говорит двигатель Regex, чтобы соответствовать @([^\s]+) только если он не предшествует слово \w. Он будет работать в примере, который вы дали, возможно, вам придется настроить его, когда идете.

Пример кода:

$pattern = "/(?<!\w)@([^\s]+)/"; 
$subject = "@fred-ii 's posts on @stackoverflow are interesting. @fred-ii 's posts [email protected]"; 

preg_match_all($pattern, $subject, $matches, PREG_SET_ORDER); 

foreach($matches as $item) 
{ 
    echo $item[1] . "<br/>"; 
} 

производит этот выход:

fred-ii 
stackoverflow 
fred-ii 

Смотрите в action.

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