PHP: разбор Юникод-строки на слова и количество гласных в ней...
Что делает пример - в заголовке. Разбор довольно примитивный, хотя, в данном случае, всё равно удобнее всего именно регулярные выражения. Логика скрипта почти такая же, как тут, только, для разнообразия, мы иначе фильтруем данные, поступившие из формы ввода и после обработки возвращаем ввод пользователя с помощью HTML-тега "скрытого поля формы".
Функции urlencode и urldecode для обмена данными между формой и скриптом применяются, скорее, для понта, хотя по правилам так и надо делать.
При работе с этими функциями следует учесть их неприятную особенность -
Будьте внимательны с переменными, которые могут совпадать с элементами HTML. Такие сущности как &, © и £ разбираются браузером и используется как реальная сущность, а не желаемое имя переменной. Это очевидный конфликт, на который W3C указывает в течение многих лет. См. подробности: http://www.w3.org/TR/html4/appendix/notes.html#h-B.2.2
Соответственно, такие "слова" как &
или "
покажут совсем "не свою" длину, а длину своих HTML-сущностей. Кроме того, даже независимо от их использования или не-использования, сущность может быть написана в HTML-форме "вручную", например, как &
.
Поэтому мы просто заменяем все русские и английские "не буквы" на пробелы с помощью preg_replace
,
бьём юникод-строку на слова с помощью preg_split
,
избавляемся от пустых "слов" с помощью array_diff
(формально этот шаг можно было и не делать),
а затем в цикле foreach
обрабатываем юникод-текст с помощью функций PHP для работы с многобайтовыми строками, находя длину каждого слова в символах, преобразуя его в верхний регистр и определяя количество русских плюс английских гласных букв, для
последней цели пришлось написать простенькую функцию mb_vowels
.
<!DOCTYPE html> <html><head> <meta charset=utf-8> <title>Строки Юникод</title></head><body> <?php $data = isset($_POST['data']) ? trim(strip_tags($_POST['data'])) : ''; if (isset($_POST['back'])) $data = urldecode($data); if (isset($_POST['action'])) { $result = ''; $count = 1; $words = preg_replace ("/[^a-zа-яё]+/msiu"," ", $data); $words = preg_split ("/[\s]+/msiu", $words); $words = array_diff ($words, array ('',' ')); foreach ($words as $w) { if (!preg_match ("/[a-zа-яё]+/msiu",$w,$matches)) continue; $w = $matches[0]; $result .= '<p>Элемент '.$count++.': <b>'.$w.'</b>, длина='.mb_strlen($w,'UTF-8'). ', регистр='.mb_convert_case($w,MB_CASE_UPPER,'UTF-8'). ', гласных='.mb_vowels($w).'</p>'."\n"; } echo '<p>'.$result.'</p>'."\n"; echo '<p><form method="post" action="'.$_SERVER['HTTP_REFERER'].'"> <input type="hidden" name="data" value="'.urlencode($data).'"> <input type="submit" name="back" value="Вернуться"> </form>'."\n"; } else { echo '<form method="post"> <input type="text" name="data" value="'.htmlspecialchars($data).'" size="40" maxlength="128"> <input type="submit" name="action" value="Отправить"> </form>'."\n"; } function mb_vowels ($s) { $vowels = "AEIOUYАЕЁИОУЫЭЮЯ"; $len = mb_strlen ($s,'UTF-8'); $cnt = 0; for ($i=0; $i<$len; $i++) if (mb_stripos ($vowels, mb_substr($s,$i,1,'UTF-8'), 0, 'UTF-8') !== false) $cnt++; return $cnt; } ?> </body></html>
Файл нужно сохранять в Юникоде (UTF-8). Чтобы работало на "Денвере", по умолчанию настроенном на Windows-кодировку, создайте в папке со скриптом файл .htaccess
с содержимым
AddDefaultCharset utf-8
Для строки
&'ABYRKA',,,,"Ёлку" тебе в 'ротовое' отверстие &&&
вывод будет таким
Элемент 1: amp, длина=3, регистр=AMP, гласных=1 Элемент 2: ABYRKA, длина=6, регистр=ABYRKA, гласных=3 Элемент 3: Ёлку, длина=4, регистр=ЁЛКУ, гласных=2 Элемент 4: тебе, длина=4, регистр=ТЕБЕ, гласных=2 Элемент 5: в, длина=1, регистр=В, гласных=0 Элемент 6: ротовое, длина=7, регистр=РОТОВОЕ, гласных=4 Элемент 7: отверстие, длина=9, регистр=ОТВЕРСТИЕ, гласных=4
То есть "amp" всё равно посчитается как слово. Но кто знает, может, юзер такое слово и хотел? :)
P.S. А вот основанный на той же идее, но более примитивный разбор строки $data
на слова, работающий при условии, что скрипт записан не в Юникоде, а в однобайтовой кодировке (русская Windows). Здесь мы не преобразуем регистр символов, но делим найденные слова на "хорошие" (состоящие только из букв) и "плохие" (в которых могут быть также дефис или цифры).
<!DOCTYPE html> <html dir="ltr" lang="ru-RU"> <head> <meta charset="windows-1251"> <title>Мини-разбор текста на слова</title> </head> <body> <?php $data = "Я текст,кото-рый нужно12 разобрать\n\nна слова.Второе предложение!"; $words = preg_replace ("/[^a-zA-Zа-яА-ЯёЁ\-0-9]+/"," ",$data); $words = preg_split ("/[\s]+/",$words); $words = array_diff ($words, array ('',' ')); foreach ($words as $word) { if (preg_match("/^[a-zA-Zа-яА-ЯёЁ]+$/",$word)) echo "<br><b>$word</b>, good"; else echo "<br><b>$word</b>, bad"; } ?> </body> </html>
P.P.S. Если нужно просто "разобрать на слова строку текста, записанную в Юникоде", легче всего это сделать по показанному ниже примеру. Сначала заботимся о цепочках разделителей, заменяя их на одиночные пробелы, потом убираем из строки всё, кроме латинских и русских букв + пробелов, естественно, можно разрешить в [^a-zа-яё\ ]
и любые другие символы.
<!DOCTYPE html> <html><head><meta charset="utf-8"><title>$words</title></head><body> <?php $data = " Хочу, чтоб жи-ли\nдолго Nobody! "; $words = preg_replace ( array ("/\s+/msui","/[^a-zа-яё\ ]/msui"), array (" ",""), $data); echo $words; ?> </body></html>
12.10.2016, 14:40 [5026 просмотров]