Мне нужно заменить каждое слово только один раз, и наоборот. Для этого я использовал код, который не работает, и я не могу найти ответ на свой вопрос.
Входные данные:
hello w1 w2 w12 new1 new12 new2
Ожидаемый результат:
hello new1 new2 w12 w1 new12 w2
Мне нужны слова / фразы в тексте, чтобы заменить.
w1 заменить new1
w12 без изменений
w2 заменить new2
new1 заменить w1
new12 без изменений
new2 заменить w2
Конечно мой текст на персидском
Мой код:
$string="hello w1 w2 w12 new1 new12 new2";
$fword= array("w1","w2");
$lword= array("new1","new2");
$cnt=0;
$string=str_replace($fword,$lword,$string,$cnt);
$string=str_replace($lword,$fword,$string,$cnt);
echo "<h2>Change in string: $cnt <br> New String: $string </h2>";
Но это неправильно
Я также использую этот код:
$string="hello w1 w2 w12 new1 new12 new2";
$fword= array("w1","w2","new1","new2");
$lword= array("new1","new2","w1","w2");
$cnt=0;
$string=str_replace($fword,$lword,$string,$cnt);
echo "<h2>Change in string: $cnt <br> New String: $string </h2>";
Вы должны использовать preg_replace. Скажите это, чтобы проверить наличие пробела или начала или конца строки (^|.*\s)
а также (\s.*|$)
чтобы избежать замены частичных совпадений.
$string="hello w1 w2 w12 new1 new12 new2";
$replacements = array(
"w1" => "new1",
"w2" => "new2",
"new1" => "w1",
"new2" => "w2");
foreach ($replacements as $from=>$to) {
$string = preg_replace(
'/(^|.*\s)'.preg_quote($from).'(\s.*|$)/',
'\1'.preg_quote($to).'\2',
$string);
}
echo $string;
если необходимо заменить только первое вхождение, вы также можете задать для этой функции ограничение 1 в качестве 4-го параметра.
Обновление: подробное объяснение
(^|.*\s)
: Первая группа совпадений: начинается строка или начинается строка с пробелом.
preg_quote($from)
: Ваша строка для замены. Цитируется для поддержки всевозможных персонажей. preg_quote () будет экранировать все символы, чтобы они не мешали управляющим кодам регулярных выражений. Также заботится о персонажах Юникода.
(\s.*|$)
: Вторая группа совпадений: конец строки или пробел, за которым следует остаток строки.
'\1'.preg_quote($to).'\2'
: Замена. Первая группа + новая строка + вторая группа.
Обновление 2:
Избавился от ненужной группы в коде и добавил экранирование, чтобы быть более общим применимым для всех видов входных данных.
Я знаю, что это долго, но я старался изо всех сил, чтобы сделать это.
<?php
ini_set("display_errors", 1);
echo $string="hello w1 w2 w12 new1 new12 new2";
$fword= array("w1","w2","new1","new2");
$lword= array("new1","new2","w1","w2");
//---------Working----------->
$replacement= array_combine($fword, $lword);
$totrimOffsets=array();
$indexes=findIndexes($fword);
$string=preg_replace("/\~\~{1,}/", "~~", $string);
$newString=replace();
//--------------------------->
echo PHP_EOL;
echo $newString;
function findIndexes($array)
{
global $totrimOffsets,$string,$replacement;
$indexes=array();
foreach($array as $element)
{
preg_match_all("/\b$element\b/i", $string,$matches,PREG_OFFSET_CAPTURE);
if(isset($matches[0]) && count($matches[0])>0)
{
foreach($matches[0] as $matchData)
{
$indexes[$element][]=array("element"=>$element,"offset"=>$matchData[1],"length"=> strlen($element));
$totrimOffsets[]=$matchData[1].",".($matchData[1]+strlen($element)-1).",".$element.",".$replacement[$element];
$string= substr_replace($string, getSpecialChars(strlen($element)), $matchData[1],strlen($element));
}
}
}
sort($totrimOffsets,SORT_NUMERIC);
return $indexes;
}
function replace()
{
global $string,$totrimOffsets,$indexes;
$stringArray=explode("~~",$string);
$newString="";
foreach($stringArray as $key => $value)
{
$newString.=$value;
if(isset($totrimOffsets[$key]))
{
$newString.=explode(",",$totrimOffsets[$key])[3];
}
}
return $newString;
}
function getSpecialChars($length)
{
$dummyString="";
for($x=0;$x<$length;$x++)
{
$dummyString.="~";
}
return $dummyString;
}
Вы можете токенизировать вашу строку с strtok
.
Затем проверьте токены в обратном цикле, и, если усеченный токен находится в списке разрешенных слов, замените его (у вас может быть массив сопоставления, например [«W1» => «E1», …]). Если такое слово уже было заменено, просто идите дальше.