Соответствие смайликам - PHP - PullRequest
1 голос
/ 12 января 2012

Мне нужно извлечь различные типы терминов из строки.Я успешно извлекаю буквенно-цифровые символы, номера валют и различные числовые форматы с помощью этого регулярного выражения:

$numalpha = '(\d+[a-zA-Z]+)';
$digitsPattern = '(\$|€|£)?\d+(\.\d+)?';
$wordsPattern = '[\p{L}]+';
preg_match_all('/('.$numalpha. '|' .$digitsPattern.'|'.$wordsPattern.')/ui', $str, $matches);

Мне также нужно сопоставлять смайлики.Я скомпилировал следующее регулярное выражение:

#(^|\W)(\>\:\]|\:-\)|\:\)|\:o\)|\:\]|\:3|\:c\)|\:\>|\=\]|8\)|\=\)|\:\}|\:\^\)|\>\:D|\:-D|\:D|8-D|x-D|X-D|\=-D|\=D|\=-3|8-\)|\>\:\[|\:-\(|\:\(|\:-c|\:c|\:-\<|\:-\[|\:\[|\:\{|\>\.\>|\<\.\<|\>\.\<|\>;\]|;-\)|;\)|\*-\)|\*\)|;-\]|;\]|;D|;\^\)|\>\:P|\:-P|\:P|X-P|x-p|\:-p|\:p|\=p|\:-Þ|\:Þ|\:-b|\:b|\=p|\=P|\>\:o|\>\:O|\:-O|\:O|°o°|°O°|\:O|o_O|o\.O|8-0|\>\:\\|\>\:/|\:-/|\:-\.|\:\\|\=/|\=\\|\:S|\:'\(|;'\()($|\W)#

, которое, кажется, работает в определенной степени: код .

Кажется, что оно не работает для смайликов, расположенныхконец строки, хотя я указал

($|\W)

внутри регулярного выражения.

------------------ EDIT-----------------

Я удалил ($ | W), как предложил Тиддо, и теперь он соответствует смайликам в конце строки.Проблема в том, что регулярное выражение, содержащее (^ | \ W), также совпадает с символом, предшествующим смайлику.

Для тестовой строки:

$str = ":) Testing ,,:) ::) emotic:-)ons ,:( :D :O hsdhfkd :(";

Соответствуют следующим:

(
[0] => :)
[1] => ,:)
[2] => ::)
[3] => ,:(
[4] =>  :D
[5] =>  :O
[6] =>  :(
)

(',', '' и ':' также совпадают в терминах ':)' и ':(')

Фрагмент кода онлайн

Как это можно исправить?

1 Ответ

1 голос
/ 12 января 2012

На самом деле, если вы измените $full присвоение этому регулярному выражению на основе положительного прогноза:

$full = "#(?=^|\W|\w)(" . $regex .")(?=\w|\W|$)#";

или просто этот без какой-либо границы слова :

$full = "#(" . $regex .")#";

Это будет работать, как вы ожидаете, без каких-либо проблем. Смотрите рабочий код здесь http://ideone.com/EcCrD

Объяснение: В исходном коде у вас было:

$full = "#(^|\W)(" . $regex . ")(\W|$)#";

Что также соответствует и захватывает границы слова . Теперь рассмотрим, когда более одного совпадающего смайлика разделены только одной границей слова, например пробелом. В этом случае регулярное выражение соответствует первому смайлику, но захватывает текст, который содержит пробел. Теперь для второго смайлика он не находит границы слова, т. Е. \W, и не может его схватить.

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

...