HungryCoder
HungryCoder

Reputation: 7616

Finding string and replacing with same case string

I need help while trying to spin articles. I want to find text and replace synonymous text while keeping the case the same.

For example, I have a dictionary like:

hello|hi|howdy|howd'y

I need to find all hello and replace with any one of hi, howdy, or howd'y.

Assume I have a sentence:

Hello, guys! Shouldn't you say hello me when I say you HELLO?

After my operation it will be something like:

hi, guys! Shouldn't you say howd'y to me when I say howdy?

Here, I lost the case. I want to maintain it! It should actually be:

Hi, guys! Shouldn't you say howd'y to me when I say HOWDY?

My dictionary size is about 5000 lines

hello|hi|howdy|howd'y go|come
salaries|earnings|wages
shouldn't|should not
...

Upvotes: 0

Views: 824

Answers (4)

Mike
Mike

Reputation: 21659

You could try the following function. Be aware that it will only work with ASCII strings, as it uses some of the useful properties of ASCII upper and lower case letters. However, it should be extremely fast:

function preserve_case($old, $new) {
    $mask = strtoupper($old) ^ $old;
    return strtoupper($new) | $mask .
        str_repeat(substr($mask, -1), strlen($new) - strlen($old) );
}

echo preserve_case('Upper', 'lowercase');
// Lowercase

echo preserve_case('HELLO', 'howdy');
// HOWDY

echo preserve_case('lower case', 'UPPER CASE');
// upper case

echo preserve_case('HELLO', "howd'y");
// HOWD'Y

This is my PHP version of the clever little perl function:

How do I substitute case insensitively on the LHS while preserving case on the RHS?

Upvotes: 0

casablanca
casablanca

Reputation: 70701

Here's a solution for retaining the case (upper, lower or capitalized):

// Assumes $replace is already lowercase
function convertCase($find, $replace) {
  if (ctype_upper($find) === true)
    return strtoupper($replace);
  else if (ctype_upper($find[0]) === true)
    return ucfirst($replace);
  else
    return $replace;
}

$find = 'hello';
$replace = 'hi';

// Find the word in all cases that it occurs in
while (($pos = stripos($input, $find)) !== false) {
  // Extract the word in its current case
  $found = substr($input, $pos, strlen($find));

  // Replace all occurrences of this case
  $input = str_replace($found, convertCase($found, $replace), $input);
}

Upvotes: 0

hsz
hsz

Reputation: 152226

You can find your string and do two tests:

$outputString = 'hi';
if ( $foundString == ucfirst($foundString) ) {
   $outputString = ucfirst($outputString);
} else if ( $foundString == strtoupper($foundString) ) {
   $outputString = strtoupper($outputString);
} else {
   // do not modify string's case
}

Upvotes: 0

Amber
Amber

Reputation: 526713

I'd suggest using preg_replace_callback with a callback function that examines the matched word to see if (a) the first letter is not capitalized, or (b) the first letter is the only capitalized letter, or (c) the first letter is not the only capitalized letter, and then replace with the properly modified replacement word as desired.

Upvotes: 1

Related Questions