БлогNot. PHP: разбор Юникод-строки на слова и количество гласных в ней...

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

Для строки

&amp;'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 [4940 просмотров]


теги: учебное язык php

К этой статье пока нет комментариев, Ваш будет первым