JavaScript replace: manipulando Strings e regex
Introdução
Em JavaScript o String replace
é utilizado com frequência para fazer desde simples substituições em Strings até complexas mudanças com expressões regulares. Seu uso é simples como variavel.replace('valor', 'substituicao')
. Eu tenho certeza que alguma vez você já precisou pegar um trecho de texto no final de um HTML, ou remover uma palavra específica de um código.
Nos formulários da web é comum termos de lidar com o campo de CPF. O que realmente importa quando colocamos um campo desses são os números, mas construindo interfaces para o usuário final é super importante mostrar para o usuário a formatação como ele está acostumado a ver nos documentos. Vamos ver como poderiamos resolver esse problema com os poderes do JavaScript e sua biblioteca padrão.
Como substituir todas as ocorrências com o apoio das Regex?
Se queremos pegar os números brutos do usuário e converter para a versão com a formatação, ou mascara de campo. Uma solução ultra direta para resolver o problema, pode ser pegarmos o valor que queremos modificar e aplicar a função .replace
das strings em cima dele.
Caso tenhamos interesse de manipular um CPF por exemplo, podemos pegar o valor do CPF puro, e falarmos que queremos convertê-lo para a sua versão amigável para o usuário:
const CPFSemFormatacao = 'cpf é 25684677037'
const CPFFormatado = CPFSemFormatacao.replace('25684677037', '256.846.770-37')
console.log(CPFFormatado)
// O retorno será 'cpf é 256.846.770-37'
A função .replace
recebe como parâmetros o padrão que estamos procurando e como segundo parâmetro o que queremos colocar no lugar
Nesse caso, nós estamos prevendo o futuro e criando um código assumindo que o usuário possui detereminado valor de CPF. Para esse uso o replace pode soar bem estranho, mas caso nosso objetivo seja restringir alguma palavra, como um palavrão, o uso acima cai como uma luva:
const frase = 'Frase com uma palavra-feia'
frase.replace('palavra-feia', '********')
console.log(frase) // O retorno seria 'Frase com uma ********')
Caso você queira visualizar esses exemplos dentro do VSCode de uma forma bem legal, eu super indico esse plugin: https://quokkajs.com/
Substituindo todas as ocorrências com o apoio das Regex
A ideia anterior de excluir palavras de um texto funciona super bem, mas se a palavra aparecer duas vezes no texto, começaremos a ter problemas:
const frase = 'Frase com uma palavra-feia e tem outra palavra-feia no final'
const fraseAtualizada = frase.replace('palavra-feia', '********')
console.log(fraseAtualizada) // O retorno seria "Frase com uma ******** e tem outra palavra-feia no final"
Repare que na segunda ocorrência da palavra que queremos remover da frase a função replace não fez nada. Isso ocorre porque quando o primeiro parâmetro da função replace é uma string, ela sempre busca a primeira ocorrência no texto base para o valor buscado. Para ter algo mais dinâmico vamos precisar recorrer ao poder das Expressões Regulares, que em resumo nos ajudam a encontrar padrões em texto de uma forma muito mais completa.
Para resolver nosso problema anterior, basta trocarmos o primeiro parâmetro passado para o replace de 'palavra-feia'
para /palavra-feia/g
. O g
no final da regex indica que queremos buscar de forma global no texto base.
const frase = 'Frase que começa com um palavra-feia e tem outra palavra-feia no final'
const fraseAtualizada = frase.replace(/palavra-feia/, '********')
console.log(fraseAtualizada) // "Frase que começa com um ******** e tem outra ******** no final"
Regex: expressões regulares
Muitos desenvolvedores, quando precisam trabalhar com Regex (regular expressions), costumam pensar "Eu sempre aprendo quando vou usar e esqueço logo em seguida". No dia a dia realmente na maioria dos casos nós não usamos Regex e se formos utilizar talvez valha mais a pena uma lib de validação como a Yup ou Joi. De todo caso, vamos dar uma relembrada que irá ser essencial para conseguirmos lidar com o caso do CPF aqui do post:
As Regex procuram padrões, a forma mais direta é escrever a própria palavra
que você deseja encontrar:
o mesmo funciona para números:
Porém, se você quiser algo mais abrangente com caracteres especiais e tudo mais, onde a ordem não importe, será necessário definir um range de caracteres:
E ainda no exemplo anterior, para pegar mais de um caracter é necessário declarar quantas ocorrências você procura:
Também é possível simplificar, para capturar somente caracteres alfa numéricos você pode usar:
Já para capturar caracteres referentes a digitos você pode usar:
E caso você queira capturar grupos dentro de um match de regex para poder trabalhar melhor como veremos nos próximos exemplos, podemos utilizar os parenteses:
Existem outros casos como utilizar a "?" para alguma parte da regex ser opcional, os marcadores de começo "^" e fim "$", mas isso tudo renderia uma série de posts ou mesmo um curso.
Caso queira ir mais a fundo, vou deixar esse guia de bolso que eu sempre uso e se quiser aprender pra valer do 0 mesmo como trabalhar com expressões regulares, vou deixar como dica esse curso de regex.
Resgatando group matches com a função replace
Agora que relembramos um pouco mais sobre as expressões regulares, podemos usar a ideia de procurar padrões encaixando em grupos e usar no segundo parâmetro do .replace
o "$
" seguido do número correspondente ao grupo na ordem em que a Regex foi escrita:
const cpf = '12345679810'
const cpfFormatado = cpf.replace(/(\d{3})?(\d{3})?(\d{3})?(\d{2})/, "$1.$2.$3-$4")
console.log(cpfFormatado) // O retorno seria 256.846.770-37
Caso você queira fazer algo mais complexo e somente passar uma string resgatando os grupos não seja o suficiente, você também pode passar uma função no lugar da string no segundo parâmetro:
const cpf = '12345679810'
const cpfFormatado = cpf.replace(/(\d{3})?(\d{3})?(\d{3})?(\d{2})/, function(matchDaRegex, grupo1, grupo2, grupo3, grupo4) {
console.log(arguments) // é uma forma de visualizar todos os parâmetros que essa função está recebendo, o numero de grupos pode variar e assim fica fácil de debugar.
return `${grupo1}.${grupo2}.${grupo3}-${grupo4}`;
})
console.log(cpfFormatado) // O retorno seria 256.846.770-37
Dúvidas comuns em manipulação de strings com Regex
- Capturando conteúdo entre abertura e fechamento de uma tag. Tome cuidado, nesses casos. O HTML é uma estrutura que é impossível de ser parseada de forma perfeita via regex, sempre prefira usar a API do DOM para manipular HTML ou uma lib como o JSDOM para converter um texto para a estrutura de arvore e facilitar a extração de conteúdo.
- Dando match em slugs
- Lidando com hexadecimais
- Trabalhando com URLs
Métodos de String
Há muitos métodos essenciais na String, alguns outros interessantes:
- split: É ultra útil quando você quer quebrar uma string em uma ou mais partes agrupadas em um array.
- trim: É muito usada ao receber um input do usuário para remover espaços em branco antes do começo da string e após o último caracter que não seja um espaço em branco.
- includes: Essa é minha função favorita das strings, ela retorna
true
oufalse
se houver ou não, respectivamente, na string base o valor que você passa como argumento para o.includes()
.
Bibliotecas para manipulação de Strings
- Existe uma lib muito popular para lidar com datas chamada MommentJS https://momentjs.com/, é necessário ter alguns cuidados quando for utiliza-la então deixo a dica desse outro link que talvez tenha alguma alternativa que possa lhe atender tão bem quanto https://github.com/you-dont-need/You-Dont-Need-Momentjs;
- Se você quiser lidar com mascaras e formatação (ajuda no cpf, telefone, cnpj...), deixo essa lib aqui https://www.npmjs.com/package/mask-js;
- Libs super bacanas para lidar com validação por schema: Yup ou Joi;
- Não é o foco do post, mas lidar com formatação e operações em cima de dinheiro pode ser algo bem complicado https://sarahdayan.github.io/dinero.js/;
- Caso você queira garantir que um input do usuário esteja realmente seguro para ser salvo na sua base de dados, é importante usar uma lib que faça o papel de remover possíveis conteúdos que gerariam injeção de scripts como essa aqui https://github.com/apostrophecms/sanitize-html
Se você for curioso como eu, deixo a dica para ver como manipular Strings em Python, e de quebra esse site super maneiro https://regex101.com que eu tenho certeza que vai ti ajudar bastante a criar regex de um jeito rápido e fácil de testar.
Nesse post nós abordamos uma série de tópicos importantes com relação a manipulação strings. Vimos os poderes do replace
, casos comuns de tratamento de strings e espero que esse post ajude tanto você, quanto algum amigo seu que pode estar agora sofrendo querendo validar um CPF ou algum dos exemplos que vimos anteriormente.
Se você curtiu, não deixe de seguir minhas redes sociais e dar uma olhadinha no meu site que toda semana está saindo algo novo por lá. Até a próxima :)