skip to Main Content

I am trying to use str_replace() to replace consonants which are not followed by a vowel with the consonant then an e. So, lb should become leb.

Conversely, a string like la should not become lea, but remain la because the l is followed by a vowel.

$phrase = "ol sonf"; 
$key = ["l", "n", "s" ,"f"];
$replace = ["le","ne","se","fe"];

$newPhrase = str_replace($key, $replace, $phrase);

echo $phrase;
echo "</br></br></br>";
echo $newPhrase;

results: ol sonf = ole seonefe

but should be:

ol sonf = ole sonefe

s is a consonant but as it is next to a vowel so — in this case it should not be replaced, same rule should be applied to all vowels A, E, I, O, U.

I mean it should only apply e to silent consonants.

2

Answers


    • Match an f, l, n, or s.
    • Forget that matched letter with K.
    • Qualify the match if the next letter not a vowel.
    • Replace the empty match with e (effectively add the e on that position)

    Code: (Demo)

    $phrase = "ol sonf";
    echo preg_replace('/[flns]K(?![aeiou])/', 'e', $phrase);
    // ole sonefe
    

    I recommend matching the listed consonant then restarting the fullstring match versus using a lookbehind (/(?<=[flns])(?![aeiou])/) as a matter of pattern efficiency. The regex engine can traverse the input string roughly 3x faster using my match&release technique versus making a lookbehind at every character position in the string.

    There are many examples on Stack Overflow of contributors implementing a zero-width match with only a lookbehind followed by a lookahead. When you see them, remember this page. In virtually all cases, you will be able to optimize the pattern by replacing the lookbehind with a match&release subpattern.


    Maybe a metaphor will help to crystalize the approach. Imagine you are running a marathon and want to know if chewing gum becomes stuck to the bottom of your shoe.

    • The lookbehind&lookahead pattern is like checking the bottom of each your shoe every time you take a step toward the finish line (of a marathon!).

    • Due to your sense of sight and touch, you will be able to identify when you step on a wad of chewing gum. When you sense that there is reason to check your shoe for lodged debris, THEN you actually bend your leg to be able to check your sole. This is how the match&lookahead works. It is very sensible to not check your shoe after every step.

    *note: I have no idea why you are doing this or even what language this is.

    Login or Signup to reply.
  1. Let’s allow ourselves a bit of madness by using the transliterator of intl:

    $phrase = 'ol sonf';
    
    $tsl = Transliterator::createFromRules('([f l n s]) } [^ a e i o u] > $1 e');
    
    echo $tsl->transliterate($phrase);
    

    Note that the syntax of this rule is very similar to a regex pattern:

    • the capture group: use of round brackets, and of a reference in the replacement part
    • the right context } that acts like a lookahead
    • character sets, similar to character classes with free-spacing

    But there’s a subtle difference in the negated character set, this one contains the Æther that matches the end of the string.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search