How to insert a letter between two words in a php string? [closed]

-1

I have to insert a monosyllable between two words within a string in PHP, as in the examples below:

// entrada
string=> vinte cinco 
// saída
string=> vinte e cinco
// entrada
string=> vinte cinco mil 
// saída
string=> vinte e cinco  mil
// entrada
string=> vinte cinco reais e vinte cinco centavos
// saída 
string=> vinte e cinco reais e vinte e cinco centavos
    
asked by anonymous 21.11.2017 / 13:19

2 answers

2

For numbers, "and" is used in the middle of these 5 cases:

  • Between tens and units, from 21 to 99.
  • Between hundreds and tens or units, from 101 to 999.
  • Between thousands and tens or units
    (Examples: two thousand and thirty , five thousand and eight ).
  • Between thousands and hundreds, only if there are dozens or units
    (Example: eight thousand and four hundred ).
  • Between millions and tens or units
    (Example: two million and thirty-one ).
  • We can use a regular expression to find the position where there should be an "e". regex101.com

    /
    
    # Definição de ordens
    (?(DEFINE)(?P<unidades>            um|dois|tr[eê]s|quatro|cinco|meia|se(?:is|te)|oito|nove                        ))
    (?(DEFINE)(?P<dezenas_dez>         d(?:ez(?:e(?:nove|sse(?:is|te))|oito)?|oze)|onze|treze|catorze|quinze          ))
    (?(DEFINE)(?P<dezenas_exceto_dez>  vinte|trinta|(?:quar|cinqu|se(?:ss|t)|oit|nov)enta                             ))
    (?(DEFINE)(?P<dezenas>             (?P>dezenas_dez)|(?P>dezenas_exceto_dez)                                       ))
    (?(DEFINE)(?P<dezenas_ou_unidades> (?P>dezenas)|(?P>unidades)                                                     ))
    (?(DEFINE)(?P<centenas>            ce(?:m|ntos?)|(?:qu(?:atroc|inh)|(?:du|tre|se(?:is|te)|oito|nove)[cz])entos?   ))
    (?(DEFINE)(?P<mil>                 mil                                                                            ))
    (?(DEFINE)(?P<milhoes>             (?:(?:[mb]|tr)i|qu(?:atri|inqua))lh(?:[aã]o|[oõ]es)                            ))
    (?(DEFINE)(?P<s>                   [ ]+                                                                           ))
    (?(DEFINE)(?P<e>                   e(?P>s)                                                                        ))
    
    
    #Regras
    \b(?:
    
        #1. Entre dezenas>=20 e unidades
        (?P>dezenas_exceto_dez)(?P>s)(?=(?P>unidades)\b)
    |
        #2. Entre centenas e dezenas ou unidades
        (?P>centenas)(?P>s)(?=(?P>dezenas_ou_unidades)\b)
    |
        #3-4. Entre milhares...
        (?P>mil)(?P>s)(?=
            (?:
                #3. ... e dezenas ou unidades
                (?P>dezenas_ou_unidades)
            |
                #4. ... e centenas, somente se não houver dezenas ou unidades
                (?P>centenas)(?!(?P>s)(?P>e)?(?P>dezenas_ou_unidades)\b)
            )
            \b
        )
    |
        #5. Entre milhões e dezenas ou unidades (que não sejam unidades ou dezenas de milhões ou unidades ou dezenas de milhares)
        (?P>milhoes)(?P>s)(?=
            (?P>dezenas_ou_unidades)(?!(?P>s)(?P>e)?(?:(?P>unidades)(?P>s)(?P>e)?)?(?:(?P>milhoes)|(?P>mil))\b)\b
    
        )
    
    )
    \b
    
    #Reset
    \K
    
    /iux
    

    Or, in a single line, no comments:

    /(?(DEFINE)(?P<unidades>um|dois|tr[eê]s|quatro|cinco|meia|se(?:is|te)|oito|nove))(?(DEFINE)(?P<dezenas_dez>d(?:ez(?:e(?:nove|sse(?:is|te))|oito)?|oze)|onze|treze|catorze|quinze))(?(DEFINE)(?P<dezenas_exceto_dez>vinte|trinta|(?:quar|cinqu|se(?:ss|t)|oit|nov)enta))(?(DEFINE)(?P<dezenas>(?P>dezenas_dez)|(?P>dezenas_exceto_dez)))(?(DEFINE)(?P<dezenas_ou_unidades>(?P>dezenas)|(?P>unidades)))(?(DEFINE)(?P<centenas>ce(?:m|ntos?)|(?:qu(?:atroc|inh)|(?:du|tre|se(?:is|te)|oito|nove)[cz])entos?))(?(DEFINE)(?P<mil>mil))(?(DEFINE)(?P<milhoes>(?:(?:[mb]|tr)i|qu(?:atri|inqua))lh(?:[aã]o|[oõ]es)))(?(DEFINE)(?P<s> +))(?(DEFINE)(?P<e>e(?P>s)))\b(?:(?P>dezenas_exceto_dez)(?P>s)(?=(?P>unidades)\b)|(?P>centenas)(?P>s)(?=(?P>dezenas_ou_unidades)\b)|(?P>mil)(?P>s)(?=(?:(?P>dezenas_ou_unidades)|(?P>centenas)(?!(?P>s)(?P>e)?(?P>dezenas_ou_unidades)\b))\b)|(?P>milhoes)(?P>s)(?=(?P>dezenas_ou_unidades)(?!(?P>s)(?P>e)?(?:(?P>unidades)(?P>s)(?P>e)?)?(?:(?P>milhoes)|(?P>mil))\b)\b))\b\K/iux
    


    Substituting text: 'e ' .


      

    I set the limit for quinquallhão (10 ^ 18). You can either complete it, or use:

    (?(DEFINE)(?P<milhoes>\w+lh(?:[aã]o|[oõ]es)))
    
         

    as a generalized case.


    Code:

    <?php    // https://pt.stackoverflow.com/q/257031/53463
    
    $re = '/
            # Definição de ordens
            (?(DEFINE)(?P<unidades>            um|dois|tr[eê]s|quatro|cinco|meia|se(?:is|te)|oito|nove                        ))
            (?(DEFINE)(?P<dezenas_dez>         d(?:ez(?:e(?:nove|sse(?:is|te))|oito)?|oze)|onze|treze|catorze|quinze          ))
            (?(DEFINE)(?P<dezenas_exceto_dez>  vinte|trinta|(?:quar|cinqu|se(?:ss|t)|oit|nov)enta                             ))
            (?(DEFINE)(?P<dezenas>             (?P>dezenas_dez)|(?P>dezenas_exceto_dez)                                       ))
            (?(DEFINE)(?P<dezenas_ou_unidades> (?P>dezenas)|(?P>unidades)                                                     ))
            (?(DEFINE)(?P<centenas>            ce(?:m|ntos?)|(?:qu(?:atroc|inh)|(?:du|tre|se(?:is|te)|oito|nove)[cz])entos?   ))
            (?(DEFINE)(?P<mil>                 mil                                                                            ))
            (?(DEFINE)(?P<milhoes>             (?:(?:[mb]|tr)i|qu(?:atri|inqua))lh(?:[aã]o|[oõ]es)                            ))
            (?(DEFINE)(?P<s>                   [ ]+                                                                           ))
            (?(DEFINE)(?P<e>                   e(?P>s)                                                                        ))
    
    
            #Regras
            \b(?:
    
                #1. Entre dezenas>=20 e unidades
                (?P>dezenas_exceto_dez)(?P>s)(?=(?P>unidades)\b)
            |
                #2. Entre centenas e dezenas ou unidades
                (?P>centenas)(?P>s)(?=(?P>dezenas_ou_unidades)\b)
            |
                #3-4. Entre milhares...
                (?P>mil)(?P>s)(?=
                    (?:
                        #3. ... e dezenas ou unidades
                        (?P>dezenas_ou_unidades)
                    |
                        #4. ... e centenas, somente se não houver dezenas ou unidades
                        (?P>centenas)(?!(?P>s)(?P>e)?(?P>dezenas_ou_unidades)\b)
                    )
                    \b
                )
            |
                #5. Entre milhões e dezenas ou unidades (que não sejam unidades ou dezenas de milhões ou unidades ou dezenas de milhares)
                (?P>milhoes)(?P>s)(?=
                    (?P>dezenas_ou_unidades)(?!(?P>s)(?P>e)?(?:(?P>unidades)(?P>s)(?P>e)?)?(?:(?P>milhoes)|(?P>mil))\b)\b
    
                )
    
            )
            \b
    
            #Reset
            \K
    
        /iux';
    
    $subst = 'e ';
    
    
    //Exemplos     
    $teste = [
                'vinte cinco',
                'vinte cinco mil',
                'vinte cinco reais',
                'vinte cinco reais e vinte cinco centavos',
                'aaa bbb ccc',
                'dois mil trezentos',
                'dois mil trezentos quarenta cinco',
                'dois milhões trinta um',
                'dois milhões trinta um mil',
                'dois milhões trinta mil',
                'dois milhões trinta um',
                'cento vinte três milhões quatrocentos cinquenta seis mil setecentos oitenta nove'
            ];
    
    //Substituir
    $resultado = preg_replace($re, $subst, $teste);
    
    
    //Mostrar em uma única matriz
    $resultado_final = array_combine( $teste, $resultado);
    var_export($resultado_final);
    

    Result:

    array (
      'vinte cinco' => 'vinte e cinco',
      'vinte cinco mil' => 'vinte e cinco mil',
      'vinte cinco reais' => 'vinte e cinco reais',
      'vinte cinco reais e vinte cinco centavos' => 'vinte e cinco reais e vinte e cinco centavos',
      'aaa bbb ccc' => 'aaa bbb ccc',
      'dois mil trezentos' => 'dois mil e trezentos',
      'dois mil trezentos quarenta cinco' => 'dois mil trezentos e quarenta e cinco',
      'dois milhões trinta um' => 'dois milhões e trinta e um',
      'dois milhões trinta um mil' => 'dois milhões trinta e um mil',
      'dois milhões trinta mil' => 'dois milhões trinta mil',
      'cento vinte três milhões quatrocentos cinquenta seis mil setecentos oitenta nove' => 'cento e vinte e três milhões quatrocentos e cinquenta e seis mil setecentos e oitenta e nove',
    )
    

    ideone.com

        
    21.11.2017 / 17:00
    2

    example - ideone

    $result="";
    
    $str = 'vinte cinco reais e vinte cinco centavos'; 
    
    /*****Opcional, para prevenir entradas adversas****/
    //Primeiro usa o trim() para limpar os espaços do início e do final da string.
    //preg_replace() para remover os espaços duplicados.
    //O caracter de escape \s significa "qualquer espaço em branco".
    //A notação (?=) é usada para realizar pesquisa adiante. Na prática ele significa "qualquer espaço que é seguido por outro espaço". Isso remove os duplicados, deixando apenas um espaço em branco.
    $str=trim(preg_replace('/\s(?=\s)/', '', $str));
    /*****fim, para prevenir entradas adversas****/
    
    //substitue todos os caracteres " e " por " " na string
    $str = str_replace(" e ", " ", $str);
    
    //cria array
    $a = explode(" ",$str);
    
    //itera o array e concatena " e " quando necessário
    for($i=0; $i < count($a); $i++){
    
          //interrompe o laço for para evitar o erro Notice: Undefined offset para "$a[$i+1]" caso fosse realizado a ultima iteraçao
          if($i == count($a)-1){
            $result = $result . $a[$i];
            break;
          }
    
          //concatena  " e " quando necessário
          if (($a[$i+1]=="reais")||($a[$i+1]=="mil")||($a[$i+1]=="centavos")){
            $result = $result . $a[$i] . " ";
          }else{
            $result = $result . $a[$i] . " e ";
          }
    
    }
    
    echo $result;
    
      

    to answer the question from the @ R.Santos'

    One thousand one hundred ten? How would it look? '

      

    Just include this condition ($a[$i+1]=="cento") more in this line

    if (($a[$i+1]=="reais")||($a[$i+1]=="mil")||($a[$i+1]=="centavos")){
    
      

    21.11.2017 / 16:31