ФорумПрограммированиеPHP для идиотов → Помогите выделить целое слово на русском с помощью регулярного выражения!

Помогите выделить целое слово на русском с помощью регулярного выражения!

  • timdenice

    Сообщения: 9 Репутация: N Группа: Кто попало

    Spritz Фев. 9, 2010, 12:12 д.п.

    Добрый день всем!
    Полдня ломаю голову над проблемой - не могу написать правильно регулярку с выделением слова на русском или еще каком языке, кроме английского. например во фразе "Mister Mi drink a milk" выделяем только слово milk таким выражением /\b(milk)\b/ все работает на ура! Но если во фразе "Маленький Мук мал да удал" попробовать выделить слово мал таким способом /\b(мал)\b/ вхождений не находит. Проблема еще в том, что я не могу использовать setlocale чтобы исправить положение, так как слово поиска генерируется из PHP но сравнение происходит на JS и сравнивает скрипт с контентом из сайта. Пробовал сделать с помощью перекодировки строки в ASCII но не нашел функции которая делает это с кириллицей, нашел с французским, но толку от нее тоже мало , потому что приходится отрывать по букве и перекодировать в php-скрипте, а так как строка возвращается в utf8 substr работает некорректно, принимая специальные символы (типа наших ю,б и т.д.) за два бита, а вот напрямую если поставить только букву перекодирует нормально, но только не русский ( привожу код функции переводировки в ascii
    <?php
        function uniord($ch) { 
    
        $n = ord($ch{0}); 
    
        if ($n < 128) { 
            return $n; // no conversion required 
        } 
    
        if ($n < 192 || $n > 253) { 
            return false; // bad first byte || out of range 
        } 
    
        $arr = array(1 => 192, // byte position => range from 
                     2 => 224, 
                     3 => 240, 
                     4 => 248, 
                     5 => 252, 
                     ); 
    
        foreach ($arr as $key => $val) { 
            if ($n >= $val) { // add byte to the 'char' array 
                $char[] = ord($ch{$key}) - 128; 
                $range  = $val; 
            } else { 
                break; // save some e-trees 
            } 
        } 
    
        $retval = ($n - $range) * pow(64, sizeof($char)); 
    
        foreach ($char as $key => $val) { 
            $pow = sizeof($char) - ($key + 1); // invert key 
            $retval += $val * pow(64, $pow);   // dark magic 
        } 
    
        return $retval; 
    } 
    
    $str='привет';
    
    $s='';
    echo "alert('".$str."');";
    
    
    
    echo "alert('".hexdec(uniord(substr($str,6,1)))."');";
    ?>

    выдаю в JS потому что обработка в регулярном выражении идет в JS код ascii возращаемый функцией не соответствует букве т
  • VaseninM

    Сообщения: 2416 Репутация: N Группа: Адекваты

    Spritz Фев. 9, 2010, 12:18 д.п., спустя 5 минут 58 секунд

    , а так как строка возвращается в utf8 substr работает некорректно

    mb_substr($str, 0,1, 'UTF-8');


    Пробовал сделать с помощью перекодировки строки в ASCII но не нашел функции которая делает это с кириллицей, нашел с французским,

    iconv($str, 'UTF-8', 'CP-1251');

    Если я тебя правильно понял.

  • timdenice

    Сообщения: 9 Репутация: N Группа: Кто попало

    Spritz Фев. 9, 2010, 12:23 д.п., спустя 5 минут 11 секунд

    Спасибо , сейчас попробую! А вот с
    iconv($str, 'UTF-8', 'CP-1251');
    может и получится, но только с русским языком. У меня сервис многоязычный, а язык на котором написана строка нереально определить (((
  • VaseninM

    Сообщения: 2416 Репутация: N Группа: Адекваты

    Spritz Фев. 9, 2010, 12:28 д.п., спустя 4 минуты 53 секунды

    А как ты регуляркой пользуешься?
  • timdenice

    Сообщения: 9 Репутация: N Группа: Кто попало

    Spritz Фев. 9, 2010, 12:43 д.п., спустя 15 минут 21 секунду

    $str='привет';
    
    $s='';
    $s=mb_substr($str, 0,1, 'UTF-8');
    //echo "alert('".$str."');";
    //$str=utf8_encode($str);
    //echo "alert('".$str."');";
    
    //echo "alert('".utf8_encode( substr($str,5,1))."');";
    $ss=uniord($s);
    $stt=  "\x".dechex($ss);
    //$stt=iconv($s, 'UTF-8', 'CP-1251'); на букву п как $s выдает пустую строку
    
     echo "re= new RegExp ('\\\b($stt)\\\b','i');   
           alert('$s');
           alert('$ss');
           alert('$stt');
           alert(re);
           alert(re.test('п'));
     ";
    вот такая штука дает алерты 1.п 2.1087 3.Cf 4. /\b(Cf)\b/ 5. false
    ну вот через тест функции JS
  • VaseninM

    Сообщения: 2416 Репутация: N Группа: Адекваты

    Spritz Фев. 9, 2010, 12:45 д.п., спустя 1 минуту 37 секунд

    а вставить preg_match перед скриптом ваще никак?
  • timdenice

    Сообщения: 9 Репутация: N Группа: Кто попало

    Spritz Фев. 9, 2010, 12:47 д.п., спустя 1 минуту 57 секунд

    никак ( сравниваемая строка находится на стороне клиента , берется с помощью JS текстовые узлы на странице, происходит их анализ на наличие слов целиком, и над словами с помощью JS делаются операции
  • VaseninM

    Сообщения: 2416 Репутация: N Группа: Адекваты

    Spritz Фев. 9, 2010, 12:58 д.п., спустя 11 минут 46 секунд

    Вообще… У тебя должен работать ютф в джаваскрипте. Переводите тебе бессмысленно. Ибо кодировки разные. Ты переведи то, что отдает браузер в ютф8. У тебя не в нем?
  • timdenice

    Сообщения: 9 Репутация: N Группа: Кто попало

    Spritz Фев. 9, 2010, 1:10 д.п., спустя 11 минут 45 секунд

    utf может и работает, но мне то надо использовать регулярные выражения, а они почему то utf не берут, то есть проверка идет например вот так прет /(пол)/ во фразе "половой пол" укажет на оба слова, а мне нужно только одно в таком случает по идее надо /\b(пол)\b/ но так он показывает false, если подставить вместо пол в регулярное выражение правильные символы ascii тогда прет, по крайней мере на французском прет на знаки типа é à , так вот как нормально в ascii перервести слово чтобы потом его в выражение вставить, потому что есть еще один выход но опять же тут не получается , смысл в том, чтобы во фразе найти слово пол со знаками препинания или переводом каретки или нулевым символом или пробелом до и после слова , получается /[\s|\w](пол)[\s|\w] и тоже не работает, видимо на русские буквы некоторые вещи типа \w не работают
    Спустя 95 сек.
    даже в тестере проверить типа regexpr.com выдает то же самое
  • Nyaah

    Сообщения: 574 Репутация: N Группа: Джедаи

    Spritz Фев. 10, 2010, 10:05 д.п., спустя 1 день 8 часов 54 минуты

    <?php
    
    // устанавливаем кодровку
    mb_regex_encoding('UTF-8');
    
    // паттерн для вытягивания русских слов
    $pattern = '\b([а-яА-ЯЁё]+)\b';
    
    // тестовая строка
    $text = 'Test string: у попа была собака, He love dogs? Fucking зоофил, ё!
    Хуй кстате, чтоб проверить "Й" и половой пол =)';
    
    // будущий результат
    $answer = array();
    
    // компилим регулярку
    if (mb_ereg_search_init($text, $pattern))
    {
        // получаем данные
        while ($pockets = mb_ereg_search_regs())
        {
            $answer[] = $pockets[1];
        }
        if (count($answer) == 0)
        {
            $answer[] = 'Нет русских слов';
        }
    }
    else
    {
        $answer[] = 'Корявая регулярка';
    }
    
    echo implode("<br />\n", $answer);


    Как-то так, если кодировка не utf-8, то установи свою, в теории должно работать и с другими кодировками
    Work, buy, consume, die
  • timdenice

    Сообщения: 9 Репутация: N Группа: Кто попало

    Spritz Фев. 10, 2010, 10:40 д.п., спустя 35 минут 6 секунд

    спасибо за ответ, но проблема в том, что мне нужно работать не только с русскими словами, второе проверка через регулярку идет через Javascript и я не могу знать заранее кодировку строки сравнения.
  • Nyaah

    Сообщения: 574 Репутация: N Группа: Джедаи

    Spritz Фев. 10, 2010, 11 д.п., спустя 19 минут 40 секунд

    Чисто логически подумай, если ты незнаешь в какой кодировке у тебя строка, то как твой скрипт догадается, что там юзер ввёл? Неужели многоязычный сайт и кодировки везде разные, если да, то ты сам себе злобный буратино, если нет, то в чем проблема, юзай вместо $pattern = '\b([а-яА-ЯЁё]+)\b'; это: $pattern = '\b(\w+)\b'; будет разбивать на слова на любых языках.

    Пробовал сделать с помощью перекодировки строки в ASCII но не нашел функции которая делает это с кириллицей, нашел с французским, но толку от нее тоже мало , потому что приходится отрывать по букве и перекодировать в php-скрипте, а так как строка возвращается в utf8 substr работает некорректно


    Используй mb_strlen($string, $charset)
    И вообще http://ru.php.net/manual/en/book.mbstring.php
    Work, buy, consume, die
  • Nyaah

    Сообщения: 574 Репутация: N Группа: Джедаи

    Spritz Фев. 10, 2010, 11:20 д.п., спустя 19 минут 59 секунд

    затестил, в коде поменял:
    $pattern = '\b(\w+)\b';
    
    // тестовая строка
    $text = 'Английский: Test string
    Русский: русский текст
    Французский: à côté du vôtre
    Итальянский: attività la pubblicità
    Испанский: páginas de España
    Немецкий: für beiß';


    Результат:
    array(22) {
      [0]=>
      string(20) "Английский"
      [1]=>
      string(4) "Test"
      [2]=>
      string(6) "string"
      [3]=>
      string(14) "Русский"
      [4]=>
      string(14) "русский"
      [5]=>
      string(10) "текст"
      [6]=>
      string(22) "Французский"
      [7]=>
      string(2) "à"
      [8]=>
      string(6) "côté"
      [9]=>
      string(2) "du"
      [10]=>
      string(6) "vôtre"
      [11]=>
      string(22) "Итальянский"
      [12]=>
      string(9) "attività"
      [13]=>
      string(2) "la"
      [14]=>
      string(11) "pubblicità"
      [15]=>
      string(18) "Испанский"
      [16]=>
      string(8) "páginas"
      [17]=>
      string(2) "de"
      [18]=>
      string(7) "España"
      [19]=>
      string(16) "Немецкий"
      [20]=>
      string(4) "für"
      [21]=>
      string(5) "beiß"
    }
    Work, buy, consume, die
  • timdenice

    Сообщения: 9 Репутация: N Группа: Кто попало

    Spritz Фев. 10, 2010, 11:34 д.п., спустя 14 минут 32 секунды

    не получится ( мне бы найти выражение которое например ищет в строке "половой пол сопол пол, ,пол пол " четыре слова пол , по идее регулярка такая \b(пол)\b проверь вот тут http://www.regextester.com/ не работает…
    я вот пытаюсь сделать с помощью двойной проверки , муторно конечно но другого выхода не вижу, т.е. я делю строку сплитом /(пол)/ потом собираю заново строку, и если соседние элементы правильные (элемент слева либо нулевой либо кончается не на букву либо на пробел(ы), элемент справа начинается с не буквы или пробела(ов)), то что то делаю со словом, если нет, то ничего не делаю со словом, ибо оно в словосочетании, пока что получается не очень (((
  • Nyaah

    Сообщения: 574 Репутация: N Группа: Джедаи

    Spritz Фев. 10, 2010, 12:06 п.п., спустя 31 минуту 23 секунды

    ты издеваешься чтоли? а самому проверить не судьба?
    <?php
    
    // устанавливаем кодровку
    mb_regex_encoding('UTF-8');
    
    // паттерн для разбивания текста на слова
    $pattern = '\b(пол)\b';
    
    // тестовая строка
    $text = 'половой пол сопол пол, ,пол пол';
    
    // будущий результат
    $answer = array();
    
    // компилим регулярку
    if (mb_ereg_search_init($text, $pattern))
    {
        // получаем данные
        while ($pockets = mb_ereg_search_regs())
        {
            $answer[] = $pockets[1];
        }
        if (count($answer) == 0)
        {
            $answer[] = 'Нет русских слов';
        }
    }
    else
    {
        $answer[] = 'Корявая регулярка';
    }
    
    var_dump($answer);
    /* result:
    array(4) {
      [0]=>
      string(6) "пол"
      [1]=>
      string(6) "пол"
      [2]=>
      string(6) "пол"
      [3]=>
      string(6) "пол"
    }
    */
    
    Work, buy, consume, die

Пожалуйста, авторизуйтесь, чтобы написать комментарий!