2016-11-20 6 views
0

Я ищу помощь для решения проблемы, с которой сталкиваюсь с функцией php preg_replace. Я сделал регулярное выражение, чтобы совместить аббревиатуру, аббревиатуру, ... Некоторые из них используют тире или точку для разметки букв, а некоторые - нет.Preg_replace заменить целую строку вместо первого захвата

\p{Lu}+(\p{Zs}?[.-]\p{Zs}?){1,10} 

Моя цель состоит в том, чтобы заменить тир и точку с #, и я пытаюсь использовать:

$re = '/\p{Lu}+(\p{Zs}?[.-]\p{Zs}?){1,10}/i'; 
$str ='normal text C.G. P- U.T.O .K.L. another normal text'; 
$subst = '${1}#'; 
$result = preg_replace($re, $subst, $str); 

В моем понимании это должно заменить первую группу захвата (тир или точку) и замените его на #. Но на самом деле он заменяет письмо.

Например, в этой строке C.G. P-U.T.O.K.L. Я ожидаю, что CGPUTOKL, но на самом деле у меня есть . #. #. #. #. #. #. #.

Вы можете получить доступ ко всему этому: https://regex101.com/r/gkeGiw/4.

Не могли бы вы сказать мне, где я ошибаюсь (и почему)?

Спасибо заранее,

С уважением,

Чарльз

+1

Ну, вы заменяете всю согласованную строку, вставляя первую группу захвата '$ {1}', а затем добавляя '#'. Вы должны записывать свои письма в группу, а не в точку/косую черту. Что вы пытаетесь выполнить с помощью повторения '{1,10}? –

+0

Зачем использовать '\ p {Lu}' (верхняя буква) с модификатором '/ i' (без учета регистра)? Если вы хотите только прописную букву, используйте '\ p {Lu}' без '/ i', или если вы хотите, чтобы нижний и нижний значения использовали' \ p {L} 'без'/i'. – Toto

+1

Каков ожидаемый результат для всей строки? – Toto

ответ

0

Вам нужно preg_replace_callback. Как сказал @SebastianProske, вы захватили бит, который вам не нужен. Однако вы не можете просто захватить бит, который вы хотите, внутри повторяющегося шаблона, потому что последнее совпадение перезаписывает все предыдущие, поэтому вы получите только последнюю букву каждого из них. Вы должны соответствовать всему аббревиатуре, а затем сгладить совпадение. Это предполагает, как минимум 2-х букв в аббревиатуре:

$text_abbreviation_normalised = preg_replace_callback(
    '/\p{Lu}(?:(?:\p{Zs}*[.-]\p{Zs}*)?\p{Lu}){1,9}(?:\p{Zs}*\.)?/', 
    function($matches) { 
     return preg_replace('/\P{Lu}+/', '', $matches[0]); 
    }, 
    $text 
); 

https://regex101.com/r/gkeGiw/7 для объяснения.

Это технически возможно сделать без обратного вызова, но регулярное выражение будет отвратительно.