简体   繁体   中英

How to replace string with another string and keep case in php and mysql?

I'm trying to do some sort of translator which would be able to keep text uppercase/lowercase. I need to replace it in PHP string and MySQL query too.

Example:

Potato is jumping all over the PLACE.
Potato is jumping all over the pLAcE. (optional)
Potato is jumping all over the place.
Potato is jumping all over the Place.

I want to replace word 'place' with 'garden'.

Potato is jumping all over the GARDEN.
Potato is jumping all over the gARdEe. (optional)
Potato is jumping all over the garden.
Potato is jumping all over the Garden.

It should also work with phrases.

I've created a function that will replace the word for you and keep the cases.

function replaceWithCase($source, $replacement, $string) {
    // Does the string contain the source word?
    if (strpos($string, $source) === false) {
        return false;
    }

    // If everything is uppercase, return the replacement fully uppercase
    if (ctype_upper($source)) {
        return str_replace($source, strtoupper($replacement));
    }

    // Set an array to work with
    $characters = array();

    // Split the source into characters
    $sourceParts = explode('', $source);

    // Loop throug the characters and set the case
    foreach ($sourceParts as $k => $sp) {
        if (ctype_upper($sp)) {
            $characters[$k] = true;
        } else {
            $characters[$k] = false;
        }
    }

    // Split the replacement into characters
    $replacementParts = explode('', $replacement);

    // Loop through characters and compare their case type
    foreach ($replacementParts as $k => $rp) {
        if (array_key_exists($k, $characters) && $characters[$k] === true) {
            $newWord[] = strtoupper($rp);
        } else {
            $newWord[] = strtolower($rp);
        }
    }

    return substr_replace($source, implode('', $newWord), $string);
}

// usage
echo replaceWithCase('AppLes', 'bananas', 'Comparing AppLes to pears');

Note: it is untested and might need some tweaking

function stringReplace($findStr, $replaceStr, $str)
{
    $isLowerStr = true;
    for($i=0; $i<strlen($findStr); $i++){
        if(ord($findStr[$i]) >= 97 && ord($findStr[$i])<=122){
            if(ord($replaceStr[$i]) >= 65 && ord($replaceStr[$i])<=96){
                $replaceStr[$i] = strtolower($replaceStr[$i]);
            }else{
                $replaceStr[$i] = $replaceStr[$i];
            }
        }else{
            $isLowerStr = false;
            $replaceStr[$i] = strtoupper($replaceStr[$i]);
        }
    }
    if($isLowerStr == false){
        if(strlen($replaceStr) > strlen($findStr)){
            for($i=0;$i<(strlen($replaceStr)-strlen($findStr));$i++){
                if(strtoupper($findStr) == $findStr){
                        $replaceStr[strlen($findStr)+$i] = strtoupper($replaceStr[strlen($findStr)+$i]);
                }else{
                    $replaceStr[strlen($findStr)+$i] = strtolower($replaceStr[strlen($findStr)+$i]);
                }
            }
        }
    }
    echo str_replace($findStr, $replaceStr, $str);die;
}
$findStr = 'Place';
$replaceStr = 'garden';
echo stringReplace($findStr, $replaceStr, 'Potato is jumping all over the '.$findStr.'.');

So I managed to create my own function in the end. Thanks for help and inspiration though.

function replaceWithCase($source, $replacement, $string, $pos = 0) {

    while (($pos = strpos(strtolower($string), strtolower($source), $pos))!== false) {
        $substr = mb_substr($string, $pos, strlen($source));
        $remaining = mb_substr($string, $pos + strlen($source));

        if (ctype_upper($substr)) {
            $string = substr_replace($string,strtoupper($replacement),$pos,strlen($source));
            continue;
        }

        $substrParts = preg_split('//u', $substr, null, PREG_SPLIT_NO_EMPTY);
        $replaceParts = preg_split('//u', $replacement, null, PREG_SPLIT_NO_EMPTY);
        $newWord = '';

        foreach ($replaceParts as $k => $rp) {
            if (array_key_exists($k,$substrParts))
                $newWord .= ctype_upper($substrParts[$k]) ? mb_strtoupper($rp) : mb_strtolower($rp);
            else
                $newWord .= $rp;  
        }
        $string = substr_replace($string,$newWord,$pos,strlen($source));
        $pos = $pos + strlen($source);
    }

    return $string;
}

echo replaceWithCase("place", "garden", "Potato is jumping all over the PLACE");
echo "<br>";
echo replaceWithCase("jumping", "running", "Potato is jumping all over the pLAcE");
echo "<br>";
echo replaceWithCase("jumping", "cry", "Potato is jumping all over the place");
echo "<br>";
echo replaceWithCase("all", "", "Potato is jumping all over the Place");
echo "<br>";
echo replaceWithCase(" ", ";", "Potato is jumping all over the Place", 10);
echo "<br>";

Output:

Potato is jumping all over the GARDEN
Potato is running all over the pLAcE
Potato is cry all over the place
Potato is jumping over the Place
Potato is jumping;all;over;the;Place
Use "stripos" php function


$str = 'Potato is jumping all over the pLAcEs.';
$str_new = "garden";

$str1 = str_split($str_new);
$pos    = stripos($str,'places');
$string = substr($str,$pos,6);

 $extrct = str_split($string);


$var = '';

foreach ($extrct as $key => $value) {
    if(ctype_upper($value))
    {
        $var .= strtoupper($str1[$key]);        
    }else{
        $var .= strtolower($str1[$key]);        
    }
}



$new_string = str_replace($string, $var, $str);


echo $new_string; //Potato is jumping all over the gARdEn.

Thanks @LadaB - that's a really helpful function but it also replaces partial word matches which I don't think you intended. For example if you have

$source = 'mom';
$replacement = 'mum'; // british spelling of "mom"
$string = 'Be in the moment with your Mom.';

You get: "Be in the mum ent with your Mum."

I fixed it like this:

function replaceWithCase($source, $replacement, $string, $pos = 0) {

    $regex = '/\b'.$source.'\b/i';
    preg_match_all($regex, $string, $matches, PREG_OFFSET_CAPTURE);

    foreach($matches[0] as $match) {
        $pos = $match[1];
        $substr = mb_substr($string, $pos, strlen($source));
        $remaining = mb_substr($string, $pos + strlen($source));

        if (ctype_upper($substr)) {
            $string = substr_replace($string,strtoupper($replacement),$pos,strlen($source));
            continue;
        }

        $substrParts = preg_split('//u', $substr, null, PREG_SPLIT_NO_EMPTY);
        $replaceParts = preg_split('//u', $replacement, null, PREG_SPLIT_NO_EMPTY);
        $newWord = '';

        foreach ($replaceParts as $k => $rp) {
            if (array_key_exists($k,$substrParts))
                $newWord .= ctype_upper($substrParts[$k]) ? mb_strtoupper($rp) : mb_strtolower($rp);
            else
                $newWord .= $rp;
        }
        $string = substr_replace($string,$newWord,$pos,strlen($source));
        $pos = $pos + strlen($source);
    }

    return $string;
}

Note the use of preg_match_all to get the position using $source wrapped in \\b to ensure it's only matching whole words.

Hope that helps you or someone else.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM