регулярное выражение для обнаружения чисел, написанных в виде слов - ввод UTF-8 - PullRequest
2 голосов
/ 02 сентября 2010

спасибо за ответы на:

"регулярное выражение для обнаружения чисел, написанных как слова":

регулярное выражение для обнаружения чисел, написанных как слова

У меня теперь это работает, но у меня такое же требование, но цифры, как слова, написаны на арабском (или любом другом UTF-8), а не на английском языке, поэтому:

if (preg_match("/\p{L}\b(?:(?:واحد|اثنان|ثلاثة|أربعة|خمسة|ستة|سبعة|ثمانية|تسعة|صفر|عشرة)\b\s*?){4}/", $str, $matches) > 0) 
   return true;

Не работает - яЯ погуглил и, кажется, было довольно много проблем с preg_match и строкой UTF-8, но я не смог найти ни одного из найденных предложений для работы.Любая помощь высоко ценится.

Ответы [ 3 ]

2 голосов
/ 03 сентября 2010

Обратите внимание, что \b может работать не так, как вы ожидаете. \b задает границу слова , но то, что PCRE считает символом слова, зависит от того, в какой локали запускается скрипт (посмотрите на нижнюю часть escape-последовательностей PCRE страница справочника):

Символ «слово» - это любая буква или цифра или символ подчеркивания, то есть любой символ, который может быть частью Perl «слово». Определение букв и цифр контролируется таблицами символов PCRE и может отличаться, если происходит сопоставление для конкретной локали. Например, в локали "fr" (французский) некоторые коды символов, превышающие 128, используются для букв с надстрочными знаками, и они совпадают с \ w.

Вы также можете прочитать Обработка UTF-8 с PHP (в частности, раздел о PCRE).

Вместо этого вы можете использовать lookaround в сочетании со свойством символа Unicode для эмуляции границы слова: (?<=\P{L}). Это подтверждает, что предыдущий символ не является буквой Юникода.

Так что все вместе это будет выглядеть так:

/(?<=\P{L})(?:(?:واحد|اثنان|ثلاثة|أربعة|خمسة|ستة|سبعة|ثمانية|تسعة|صفر|عشرة)\s*?){4}/
0 голосов
/ 03 сентября 2010

Вы можете использовать модификатор шаблона u для использования любого языка, поддерживаемого UTF-8.

if (preg_match("/\p{L}\b(?:(?:واحد|اثنان|ثلاثة|أربعة|خمسة|ستة|سبعة|ثمانية|تسعة|صفر|عشرة)\b\s*?){4}/u", $str, $matches) > 0) 

Ресурсы:

0 голосов
/ 02 сентября 2010

конвертируйте оба шаблона и $str в windows-1256, выполните сопоставление, затем конвертируйте $matches элементы обратно (при необходимости), это решение, к которому я пришел после некоторого страдания.

$pattern="/\p{L}\b(?:(?:واحد|اثنان|ثلاثة|أربعة|خمسة|ستة|سبعة|ثمانية|تسعة|صفر|عشرة)\b\s*?){4}/";
$pattern_windows1265 = iconv('utf-8', 'windows-1256', $pattern);
$str_windows1265 = iconv('utf-8', 'windows-1256', $str);
if (preg_match($pattern_windows1265, $str_windows1265, $matches) > 0) 
   return true;

Вот тестовый пример, чтобы проверить, позволяет ли преобразование Юникода совпадать с арабскими буквами в preg_match:

<?php
$pattern="/(واحد|اثنان|ثلاثة|أربعة|خمسة|ستة|سبعة|ثمانية|تسعة|صفر|عشرة)/";
$pattern_windows1265 = iconv('utf-8', 'windows-1256', $pattern);


$test_cases=array(
    'لدي أربعة أولاد',
    'قفز الثعلب فوق الشجرة',
    'عندي خمسة أرانب',
);
foreach ($test_cases as $str) {
    $str_windows1265 = iconv('utf-8', 'windows-1256', $str);

    if (preg_match($pattern_windows1265, $str_windows1265, $matches) > 0) {
        echo $str, '<br />';
    }
}

при выполнении выдает:

لدي أربعة أولاد
لدي خمسة أرانب

Я удалил некоторые из шаблонов, чтобы проверить, работает ли обычная проверка на арабские произведения, которая, кажется, работает.

...