Master-X
Форум | Новости | Статьи
Главная » Форум » Программинг, Скрипты, Софт, Сервисы » 
Тема: Замена слов в тексте.
цитата
31/03/12 в 07:31
 Lexikon
Решил для производственной необходимости написать код который бы заменял одни слова на другие. Но тут столкнулся с проблемой.
в скрипте использую такую структуру замены:

<?php

$text = "I'm already here. I've seen that movie several times. I'll deal with this.";
$search = Array("I'm", "I've", "I'll");
$replace = Array("I am", "I have", "I will");
$newtext = str_replace($search, $replace, $text);

echo $newtext;

?>


всё конечно хорошо работает, но тут проблема с регистрами букв, если слово поиска начинается с строчной буквы, а слово замены с заглавной, то замена не произойдет.
Как пример вот это предложение: "Это предложение начинается с большой буквы. Сново же и это предложение начинается с большой буквы.
Допустим нужно заменить "Это предложение" на "Мой текст" в первом предложении замена произойдет, а вот во втором уже нет.
Как быть х.з. единственное пришел к выводу это делать так: Перевести всё в нижний регистр, и слова замены использовать тоже с маленькой буквы, затем разбить текст на массив используя как резделитель точку и уже с помощью ucfirst() изменить каждую строку массива и потом собрать содержимое массива в одну строку.

Может это бред, но пока только такая мысль, ибо знаний и практики еще маловато. Да и в таком варианте есть минусы в том что иногда в тексте встречаются имена, а значит они после такой обрамотки остануться с маленькой буквы. Да и окончание предложения не всегда точкой заканчиваются. Вероятно тут может быть выриант с регулярками, но х.з. буду пока рыться. Попробую еще поиграть с содержимым массива и ucfirst(), думаю тут выход найду.

Если кто то может натолкнуть на правильную мысль, буду благодарен.
цитата
31/03/12 в 08:06
 FTS
Используй str_ireplace() вместо str_replace() icon_cool.gif
Функция str_ireplace() нечувствительна к регистру.
цитата
31/03/12 в 08:56
 Lexikon

<?php
$text = "I'm already here. I've seen that movie several times. I'll deal with this, i'm here.";
$search = Array("i'm", "i've", "i'll");                                                  
$replace = Array("i am", "i have", "i will");                                                
$newtext = str_ireplace($search, $replace, $text);

echo $newtext;
?>


да замена происходит, но на выходе всё с маленькой буквы (это конечно потому т.к. в $replace всё с маленькой, но сделав запись с большой буквы я получу в тексте всё это с большой буквы и тут станет вопрос опять же - как сделать правильно выглядещее предложение.) даже если я результат загоню в ucfirst($newtext); то на выходе получу только первое предложение с большой буквы.
цитата
31/03/12 в 09:09
 FTS
Кстати, I применительно к себе в английском всегда пишется с большой буквы, будь оно в начале, в середине или в конце предложения.
То есть в приведённом тобой примере можно поставить:
$replace = Array("I am", "I have", "I will");
цитата
31/03/12 в 09:14
 Lexikon
это как пример icon_wink.gif , там будут другие слова.
цитата
31/03/12 в 09:25
 samedi
Код:
<?php

$input = "I'M ALREADY HERE. I've seen that movie several times. I'll deal with this, i'm here.";

$replace_list = array(
    "i'm" => "i am",
    "i've" => "i have",
    "i'll" => "i will"
);

foreach ($replace_list as $find => $replace) {
    while (($pos = stripos($input, $find)) !== false) {
        $word_old = substr($input, $pos, strlen($find));
        $mask = strtoupper($word_old) ^ $word_old;
        $word_new = strtoupper($replace) | $mask .
            str_repeat(substr($mask, -1), strlen($replace) - strlen($word_old));
        $input = str_replace($word_old, $word_new, $input);
    }
}

echo $input;

Код:
I AM ALREADY HERE. I have seen that movie several times. I will deal with this, i am here.


Стукнись в личку - скажу куда отсылать коньяк.
цитата
31/03/12 в 13:10
 kodek
Цитата:
Если кто то может натолкнуть на правильную мысль, буду благодарен.

Хм.. А почему бы просто дважды не проходиться по массиву? Один раз - с заглавными буквами, второй - приведя их же к нижнему регистру (ну и массив замен тоже, соответственно).
цитата
31/03/12 в 13:27
 Lexikon
kodek писал:
Хм.. А почему бы просто дважды не проходиться по массиву? Один раз - с заглавными буквами, второй - приведя их же к нижнему регистру (ну и массив замен тоже, соответственно).

Занимался этим вопросом, сразу, но стопрнулся на моменте когда нужно было всё в массив собрать обратно.
Т.е. вот к примеру в этом куске.

$bigReplace = ucfirst($bigReplace)."|";
$bigReplace = explode("|", $bigReplace);
echo $bigReplace;


Читаем массив который написан маленькими буквами, затем его переводим в заглавные, разделяем слова вертикальной чертой и получаем соответственно (I am|I have|I will|
и I'm|I've|I'll|), но в браузере это видно как строку, но пытаясь это записхнуть в массив с помощью explode("|", ....) ничего не вышло, каждое слово было отденьным содержимым массива.


<?php
$text = "I'm already here. I've seen that movie several times. I'll deal with this, i'm here.";
$smallSearch = Array("i'm", "i've", "i'll");                                                  
$smallReplace = Array("i am", "i have", "i will");                               

foreach ($smallReplace as $bigReplace)
      {
      $bigReplace = ucfirst($bigReplace)."|";
      $bigReplace = explode("|", $bigReplace);   
      echo $bigReplace;
      }

echo "<br>";
      
foreach ($smallSearch as $bigSearch)
      {
      $bigSearch = ucfirst($bigSearch)."|";
      $bigSearch = explode("|", $bigSearch);   
      echo $bigSearch;
      }

$newtext = str_replace($smallSearch, $smallReplace, $text);

//echo ucfirst($newtext);

?>    
цитата
31/03/12 в 14:58
 kodek
Мне кажется, проблема в том, что ты в цикле foreach работаешь не с самим массивом, а с его отображением. Ты читаешь элементы $smallReplace в переменную $bigReplace, и с ней работаешь, оригинальный массив ведь не меняется при этом. Обращайся к массиву напрямую тогда!

Вот так вот, будут меняться уже сами элменты массива (обрати внимание на символ & перед $bigReplace):
Код:
foreach ($smallReplace as &$bigReplace)
цитата
31/03/12 в 15:04
 kodek
Короче - вот так попробуй. Если я правильно понял логику =)
И explode там вообще не нужен!

Код:
<?php

$text = "I'm already here. I've seen that movie several times. I'll deal with this, i'm here.";
$smallSearch = Array("i'm", "i've", "i'll");
$smallReplace = Array("i am", "i have", "i will");

// первый проход - замена строчных
$newtext = str_replace($smallSearch, $smallReplace, $text);

foreach ($smallReplace as &$bigReplace)
      {
      $bigReplace = ucfirst($bigReplace);
      }
foreach ($smallSearch as &$bigSearch)
      {
      $bigSearch = ucfirst($bigSearch);
      }

// второй проход - замена прописных
$newtext = str_replace($smallSearch, $smallReplace, $newtext);

echo $text."<br>".$newtext;

?>
цитата
31/03/12 в 15:24
 Lexikon
хммм, сейчас буду разбираться, где закосячил, ибо почти один в один у иеня код получился, но не работает так как нужно.
Спасибо!
цитата
02/04/12 в 09:46
 Lexikon
код от samedi отличный, но вот если приходиться менять к примеру
"i'm" => "i'm here"
скрипт уходит в бесконечный цикл icon_confused.gif
во втором вариианте такого нет, но второй вариант не работает с ТАКИМ ТЕКСТОМ.
Первый вариант если бы не впадал в цикл был бы именно тем что хотел.
Пытался как то заставить не зацикливаться, но в моих случиях получалось что происходила первая замена и всё.
массив
$replace_list = array(
"i'm" => "i am",
"i've" => "i have",
"i'll" => "i will"
);

может содержать до полусотни строк, и сколько замен будет в тексте предсказать невозможно.

Т.е. в таком варианте, получается бесканечный цикл:


<?php

$input = "I'M ALREADY HERE. I've seen that movie several times. I'll deal with this, i'm here.";

$replace_list = array(
     "i'm" => "i'm here",
     "i've" => "i have",
     "i'll" => "i will"
);

foreach ($replace_list as $find => $replace) {
     while (($pos = stripos($input, $find)) !== false) {
         $word_old = substr($input, $pos, strlen($find));
         $mask = strtoupper($word_old) ^ $word_old;
         $word_new = strtoupper($replace) | $mask .
             str_repeat(substr($mask, -1), strlen($replace) - strlen($word_old));
         $input = str_replace($word_old, $word_new, $input);
     }
}

echo $input;

?>
цитата
02/04/12 в 10:44
 idk2045
вот как вариант.
недостаток что строки поиска надо писать в виде регулярного выражения, но это довольно легко.
каждую строку оборачивай в ``is, i значит нечувствительный к регистру, s поиск по всему тексту, если текст состоит из нескольких строк.
буквы для которых хочешь сохранить регистр оборачивай в скобки, и потом обращайся к ним как $1, $2 и т.п. по порядковому номеру скобок.
Код:
<?
$text = "I'm already here. I've seen that movie several times. i'll deal with this.";
$search = Array("`(I)'m`is", "`(I)'ve`is", "`(I)'ll`is");
$replace = Array("$1 am", "$1 have", "$1 will");
$newtext = preg_replace($search, $replace, $text);
echo $newtext;
цитата
02/04/12 в 13:28
 FXIX
Lexikon писал:
Решил для производственной необходимости написать код который бы заменял одни слова на другие. Но тут столкнулся с проблемой.
в скрипте использую такую структуру замены:

<?php

$text = "I'm already here. I've seen that movie several times. I'll deal with this.";
$search = Array("I'm", "I've", "I'll");
$replace = Array("I am", "I have", "I will");
$newtext = str_replace($search, $replace, $text);

echo $newtext;

?>

всё конечно хорошо работает, но тут проблема с регистрами букв, если слово поиска начинается с строчной буквы, а слово замены с заглавной, то замена не произойдет.



ну примерно так.
Цитата:

$data = array(
array("I'm" => "I am"),
array("i'm" => "i am"),
array("I've" => "I have"),
array("i've" => "i have"),
);
foreach ($data as $k => $v) {
preg_replace("~(" . $k . ")~s", $v, $subject);
}

$subject - это текст.
$data - это слова из двух файлов. в одном исходное. в другом замена. ну номер строки должен совпадать.

быстро в один файл 30-50 слов набил. быстро в другой скопипастил. буквы заменил на маленькие.

можно и второй файл генерить. зависит от объемов твоих...


Эта страница в полной версии