Я хочу извлечь фразы из урду из строки, представленной пользователем в PHP. Для этого я попробовал следующий тестовый код:
$pattern = "#([\x{0600}-\x{06FF}]+\s*)+#u"; if (preg_match_all($pattern, $string, $matches, PREG_SET_ORDER)) { print_r($matches); } else { echo 'No matches.'; }
Теперь, если, например, $string
содержит
In his books (some of which include دنیا گول ہے, آوارہ گرد کی ڈائری, and ابن بطوطہ کے تعاقب میں), Ibn-e-Insha has told amusing stories of his travels.
Я получаю следующий вывод:
массив ( [0] => Массив ( [0] => دنیا گول ہے [1] => ہے ) [1] => Массив ( [0] => آوارہ گرد کی ڈائری [1] => ڈائری ) [2] => Массив ( [0] => ابن بطوطہ کے تعاقب میں [1] => میں ) )
Несмотря на то, что я получаю мои желаемые матчи ( دنیا گول ہے
, آوارہ گرد کی ڈائری
и ابن بطوطہ کے تعاقب میں
), я также получаю нежелательные ( ہے
, ڈائری
и میں
– каждый из которых на самом деле является последним словом его фразы ). Может ли кто-нибудь указать, как я могу избежать нежелательных матчей?
Это связано с тем, что группа захвата ([\x{0600}-\x{06FF}]+\s*)
сопоставляется несколько раз, каждый раз переписывая то, что соответствовало предыдущему времени. Вы можете получить ожидаемый результат, просто переведя его в группу, не (?:[\x{0600}-\x{06FF}]+\s*)
захватом – (?:[\x{0600}-\x{06FF}]+\s*)
но вот более правильная альтернатива:
$pattern = "#(?:[\x{0600}-\x{06FF}]+(?:\s+[\x{0600}-\x{06FF}]+)*)#u";
Первый [\x{0600}-\x{06FF}]+
соответствует первому слову, затем, если есть пробелы, за которыми следует другое слово, (?:\s+[\x{0600}-\x{06FF}]+)*
соответствует ему и любым последующим словам. Но после последнего слова это не соответствует пробелу, который, как я полагаю, вам не нужен.