PHP: Replace only on the first word repeated

Asked

Viewed 224 times

0

Hello, for example, I have the phrase:

My name is "Victor", the name "his" "is" "Victor", "his" name "is" "Victor"

I use a preg_replace to exchange all the words in quotation marks with the word "pineapple". Would be:

My name is "pineapple", the name "pineapple" "pineapple" "pineapple", "pineapple" name "pineapple" "pineapple"

However, how can I perform this replace only on the first repeated words in quotation marks? Example:

My name is "pineapple", the name "pineapple" "pineapple" "Vitor", "pineapple" name "is" "Vitor"

Thank you.

  • You could clarify your doubt better, see: in the sentence: My name is Vitor, his name is Vitor, his name is Vitor, if we were to hide only the first occurrence of each repetition, it would be: My pineapple pineapple pineapple, his name is Vitor, his name is Vitor and not My name is pineapple, the name pineapple pineapple Vitor, pineapple name is Vitor as exemplified by you.

1 answer

0


It may have a specific function for this, but is easy to do at hand.

Assuming the text:

My name is "Victor", the name "his" "is" "Victor", "his" name "is" "Victor"

We can simply do:

Find the ", finding get the word until the next ". This word check if it has already been replaced previously, if it does not replace and add this word in the list of "already replaced".


This is more for teaching purposes, but clearly you can do it in a more organized way.

$substituto = "abacaxi";

$posicaoInicio = -1;
$posicaoFim = -1;
$dicionario = [];


while($posicaoInicio !== false && $posicaoFim !== false){

    $posicaoInicio = strpos($texto, '"', $posicaoFim + 1);
    $posicaoFim = strpos($texto, '"', $posicaoInicio + 1);

    $palavraTamanho = ($posicaoFim - $posicaoInicio) - 1;
    $palavra = substr($texto, $posicaoInicio + 1, $palavraTamanho);

    if($posicaoInicio !== false 
       && $posicaoFim !== false 
       && in_array($palavra, $dicionario, true) === false){

        $dicionario[] = $palavra;

        $texto = substr_replace($texto, $substituto, $posicaoInicio + 1, $palavraTamanho);

        $diferencaTamanho = strlen($substituto) - $palavraTamanho;
        $posicaoFim = ($posicaoFim + $diferencaTamanho) + 1;

    }

}

Test this.

The idea is very simple, first we find the beginning and the end of the target word, ie the word that is between the quotation marks, for this we use:

 $posicaoInicio = strpos($texto, '"', $posicaoFim + 1);
 $posicaoFim = strpos($texto, '"', $posicaoInicio + 1);

strpos will find the first occurrence from the offset, therefore, assuming:

My name is "Vitor"

The first quote (start) is 12, so we need to look for the other one from 13, which will be found at position 18.

We then know that the first word is between the 13th to the 17th byte, in this case. Logico, we need to delete the quotes, for this we use:

$palavraTamanho = ($posicaoFim - $posicaoInicio) - 1;

This will be used so that 18 - 12 (= 6) then subtract 1, making 5. This is the word size.

Then we get the word:

$palavra = substr($texto, $posicaoInicio + 1, $palavraTamanho);

The beginning is 12, but 12 includes the quotation marks, so we have to add 1, thus taking the 5 bytes, corresponding to Vitor, quote-free.

Now we need to know if the word exists and if it hasn’t already been replaced, then:

$posicaoInicio !== false 
&& $posicaoFim !== false 
&& in_array($palavra, $dicionario, true) === false

This will make him have to have found the two quotes and the word cannot be inserted in $dicionario, which is an array that we will fill with the already replaced words. That is, all the words we already know (which is in the dictionary) have been changed. ;)

If it is all right and it has not been replaced we do this. We add the word in our dictionary:

$dicionario[] = $palavra;

Now we exchange the word in the text using:

$texto = substr_replace($texto, $substituto, $posicaoInicio + 1, $palavraTamanho);

This will cause you to insert the pineapple from the 13º byte with a size of 5 digits. That is, you will change the Vitor for abacaxi, he will remove the Vitor and will add the abacaxi in his stead.

If you notice, there is a problem, the abacaxi is greater in number of characters than the Vitor, so we need to calculate the $posicaoFim, after all we need to know which was the last identified quote.

That’s why we use:

$diferencaTamanho = strlen($substituto) - $palavraTamanho;
$posicaoFim = ($posicaoFim + $diferencaTamanho) + 1;

This will calculate the difference in the size of both texts (Vitor and abacaxi) and will adjust the last ". Mathematically the difference between the two is 7 - 5 (=2). Then we need to count with the quotes, adding 1, in total will be 18 + 2 + 1 (= 21). The last quote is in 21st position.

Now, we do it again, but with the dele, so on and so forth.


Browser other questions tagged

You are not signed in. Login or sign up in order to post.