Я хочу извлечь фразы из урду из строки, представленной пользователем в 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}]+)* соответствует ему и любым последующим словам. Но после последнего слова это не соответствует пробелу, который, как я полагаю, вам не нужен.