Strings Aproximadas.

    Você já teve que procurar um padrão incerto? Como strings que possam conter erros de digitação, ou algo que se “pareça”. Por exemplo, é comum errarem meu nome. De Thiago para Tiago. E uma regex /Thiago/ não acharia meu nome. Isso é fácil de resolver com /Th?iago/. Mas e se o erro de digitação estiver em outro lugar? Yago? Iago? Thigo? Vai saber o que aquele pessoal do call center digitou errado no meio de tanta pressa e tantas ligações. Mas o erro de digitação foi parar no banco de dados, não foi! Como eu posso achar possibilidades erradas para Thiago? Existe, claro um módulo CPAN para isso. O String::Approx. E a não ser que você queira criar seus próprios algoritmos para  fuzzy match (seres humanos normais não querem), você vai preferir utilizar este módulo. Perceba que módulos CPAN não são como uma cartola de mágico, eles tem uma lógica (pesada neste caso) que permite que eles executem o trabalho, e fuzzy match é um algoritmo tipicamente mais lento que um algoritmo para match ordinário, pois são necessárias mais comparações.

    Depois que você instalar o módulo CPAN ou a biblioteca equivalente da sua distro ( libstring-approx-perl no Ubuntu), podemos começar a nossa brincadeira.

      1 #!/usr/local/bin/perl
      2 use 5.12.0;
      3 use String::Approx 'amatch';
      4
      5 my @inputs;
      6 push @inputs, $_ while $_=<STDIN>;
      7
      8 my @matches = amatch("equinócio", @inputs);
      9
     10 print "\nOs matchs foram:\n";
     11 print "@matches";

./mymatch.pl
Equinócio
equinocio
equiócio

Os matchs foram:
Equinócio
 equiócio

    Vamos aumentar a complexidade. Vamos configurar a distância entre a string de referência e o texto onde pesquisamos a string. Para isto modifique a linha 8 com o código abaixo:

my @matches = amatch("equinócio", [ "i 30%" ], @inputs);

    E todas as entradas anteriores irão aparecer na saída. Isso por que colocamos no array de configuração a flag i, que significa ignore case e 30%. Isso quer dizer que até 30% de diferença entre o padrão fornecido (“equinócio”) e a string de saída são aceitáveis. Se nenhum parâmetro for fornecido, amatch aceitará até 10% de diferenças:


 ./mymatch.pl
 ./mymatch.pl
Podemos colocar textos longos
para pesquisar as possibilidades de erro da palavra equiócio
Ignorando o case, como em EQUINoci
Isto é útil para pesquisarmos possibilidades
de palvras similares em HTML, arquivos de log
ou erros de digitação em registros de bancos.
quinócio!

Os matchs foram:
 para pesquisar as possibilidades de erro da palavra equiócio
 Ignorando o case, como em EQUINoci   
 quinócio!

Mas isto ainda não é tudo que o String::Approx pode fazer por você. Ainda podemos substituir strings. Para substituirmos strings, substitua a linha 3 do script por:

use String::Approx 'asubstitute';

e a linha 8 por:

my @matches = asubstitute("equinócio", “equinócio”, [ "i 30%" ], @inputs);

e veja o que acontece. A saída muda para:

Os matchs foram:
para pesquisar as possibilidades de erro da palavra equinócio Ignorando o case, como equinócio

Todos as formas “incorretas” de equinócio foram corrigidas.

Muitas outras coisas podem ser feitas com este módulo. De uma olhada na documentação do mesmo, use sua imaginação e divirta-se. “No unnecessary limits”