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

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

  • timdenice

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

    Spritz 9 февраля 2010 г. 0: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 г. 0: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 г. 0:23, спустя 5 минут 11 секунд

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

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

    Spritz 9 февраля 2010 г. 0:28, спустя 4 минуты 53 секунды

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

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

    Spritz 9 февраля 2010 г. 0: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 г. 0:45, спустя 1 минуту 37 секунд

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

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

    Spritz 9 февраля 2010 г. 0:47, спустя 1 минуту 57 секунд

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

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

    Spritz 9 февраля 2010 г. 0: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:00, спустя 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

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