Se você não sabe o que expressão regular (também conhecido como "regex" ou "regexp"), é um linguagem incrivelmente poderosa para executar uma pesquisa e/ou substituição em qualquer tipo de texto. O Regex tem uma longa e gloriosa história (suas origens remontam aos anos 50) e, mesmo agora, você o usa todos os dias ... talvez você não saiba disso. Atualmente, o Regex está incorporado na maioria das principais linguagens de programação e sistemas de computador e é usado em uma grande variedade de aplicativos.
O regex não é mais apenas para programadores: ele está aparecendo em todos os tipos de lugares atualmente. Alguns dos lugares em que você pode tê-lo visto até agora são para correspondência de URLs no Google Analytics, pesquisa e substituição em seu editor de texto favorito (alguns editores populares que suportam regex incluem Sublime, Átomo, Nuvem9, Notepad++Google Docs e Microsoft Word ... embora o Word tenha uma sintaxe de regex que é muito não-padrão) e até mesmo nomes de arquivos correspondentes em nosso incrível plug-in de associação do WordPress, MemberPress.
Embora o regex esteja aparecendo em lugares surpreendentemente novos, sua natureza aparentemente enigmática provavelmente sempre o tornará mais usado predominantemente por programadores e "usuários avançados".
Portanto, é neste ponto do artigo que você precisa decidir se vai continuar vivendo sem conhecer o poder incalculável da regex ou se vai engolir a pílula vermelha e empunhar a espada de um usuário avançado! Neste post, darei a você o conhecimento básico necessário para começar a colocar essa ferramenta extremamente útil para trabalhar para você. Então, vamos começar!
Alguns exemplos
Qual é a aparência das declarações regex? Se você visse uma delas sem ter ideia do que se trata, ela pareceria uma grande bobagem.
Aqui está um exemplo de instrução regexp para corresponder a um número de telefone:
\(?\d{3}\)?[- ]\d{3}-\d{4}
Aqui está um que corresponde a um URL:
https?:\/\/[\w-]+(\.[\w-]{2,})*(:\d{1,5})?
E um que possa corresponder a um endereço de e-mail:
[\w\d._%+-]+@[\w\d.-]+\.[\w]{2,4}
Por fim, aqui está uma pesquisa e substituição simples que encontrará todos os nomes de domínio com o subdomínio "test" e os alterará para um subdomínio "www":
Pesquisar: test\.([^\.]+)\.com
Substituir: www.$1.com
Já se sentiu intimidado? Não seja assim. Verei como as instruções regex são interpretadas, detalhando o que estamos fazendo em cada uma dessas instruções e explicando como criar as suas próprias.
Como ler Regex
As expressões regulares são como instruções normais de localização, mas com esteroides. Por exemplo, se você quisesse encontrar o nome "Harry" em uma página da Web, clicaria em control-f e digitaria "Harry" para encontrá-lo. Com o regex, você pode fazer mais do que simplesmente procurar por "Harry". Você pode procurar por "Harry" ou "Bob" com (Harry|Bob)
Ou você pode pesquisar qualquer palavra que comece com "Ha" com Ha\S*
.
Para seu computador, o texto é representado como uma "cadeia" de caracteres. De fato, se você já ouviu programadores falando sobre código, provavelmente já os ouviu usar o termo "string" ao se referir a alguma variável.
As expressões regulares são lidas da esquerda para a direita (assim como o inglês e muitos outros idiomas) e explicam ao computador o que deve ser correspondido à medida que ele examina uma string da esquerda para a direita. À medida que o computador examina cada caractere, ele segue esse fluxo:
Se você olhar para este fluxograma, por mais complicado que possa parecer, verá algo muito familiar aqui. É praticamente idêntico ao que você esperaria qualquer A pesquisa de dados é uma forma de pesquisa que pode ser feita em um computador e como as pesquisas com as quais você se sente confortável atualmente já acontecem. O Regex apenas acrescenta alguns recursos extremamente avançados à pesquisa normal.
O básico
Agora, antes de começarmos a dissecar nossos exemplos de instruções regex acima, vamos examinar alguns dos caracteres de comando mais básicos do regex:
Repetidores: *, + e {...}
Os caracteres asterisco (*) e mais (+) são repetidores. Um repetidor só é usado depois de outro caractere ou de uma declaração anexa e diz ao computador para fazer a correspondência com o caractere anterior X vezes. O asterisco corresponderá ao caractere anterior de 0 a infinitas vezes; o sinal de mais, de 1 a infinitas vezes; {2}
corresponderá exatamente a 2 vezes; {4,6}
corresponderá exatamente entre 4 e 6 vezes; e {7,}
será igualado entre 7 e infinitas vezes.
Curinga: .
Você provavelmente está acostumado a usar o símbolo de estrela como curinga, mas ele é um ponto (.) em regex. O ponto final simplesmente corresponderá a qualquer caráter.
Opcional: ?
Assim como o repetidor, o caractere opcional, um ponto de interrogação (?), só é usado depois de outro caractere ou de uma declaração fechada. Quando ele está no lugar, informa ao computador que o caractere anterior pode ou não estar presente nos resultados da pesquisa.
Início e fim da cadeia de caracteres: ^ e $
Quando o acento circunflexo (^) é usado no início da regex, ele indica que a primeira parte da cadeia de caracteres deve ser correspondida. E o cifrão ($), quando usado no final da regex, corresponderá ao final da cadeia de caracteres.
Possíveis personagens: [...]
Os caracteres entre colchetes indicam os caracteres que podem ser combinados nessa posição. Por exemplo, se você quiser fazer a correspondência de um 'n','m','l' ou '_', poderá adicionar o seguinte à sua regex [nml_]
. Se você quisesse fazer a correspondência com qualquer letra ou número, poderia adicionar o seguinte [A-Za-z0-9]
.
Se você quiser fazer a correspondência com qualquer caractere exceto Para combinar os caracteres possíveis, basta colocar um acento circunflexo (^) após o colchete de abertura. Por exemplo, se você quiser fazer a correspondência com qualquer caractere, exceto 'x','y','z' ou '_', poderá fazer isso com a instrução: [^xyz_]
. Como você pode ver, isso pode lhe dar um controle minucioso sobre o que está sendo combinado em cada caractere.
Declarações anexas: (...)
Às vezes, você deseja fazer com que seções da sua regex se comportem como um bloco ou guardá-las para depois. Para isso, tudo o que você precisa fazer é envolver a declaração entre parênteses.
Escape: \
Agora, e se você quiser fazer a correspondência com os caracteres '+', '.' etc.? Bem, se você colocar uma barra invertida na frente dele, isso dirá ao computador que você está tentando corresponder a um caractere de pesquisa real e não o interpretará como um caractere de comando.
Caracteres de abreviação: /s, /S, /d, /D, /w, /W e /b
Esses caracteres são muito úteis e o ajudarão a combinar determinados conjuntos de caracteres. Veja como eles se dividem:
/s
corresponde a qualquer caractere de espaço em branco, como espaço e tabulação/S
corresponde a qualquer caractere que não seja um espaço em branco/d
corresponde a qualquer caractere de dígito/D
corresponde a qualquer caractere que não seja um dígito/w
corresponde a qualquer caractere de palavra (basicamente alfanumérico)/W
corresponde a qualquer caractere que não seja uma palavra/b
corresponde a qualquer limite de palavra (isso inclui espaços, traços, vírgulas, ponto e vírgula, etc.)
É claro que há muitas outras coisas mais avançadas que você pode fazer com regex, mas essas noções básicas lhe darão as ferramentas necessárias para 90% suas necessidades de pesquisa avançada.
Detalhamento do nosso exemplo de número de telefone
Agora que você tem as ferramentas, vamos examinar nossos exemplos para ver como eles funcionam, começando com nossa correspondência para o número de telefone:
\(?\d{3}\)?[- ]\d{3}-\d{4}
Portanto, vamos dividi-lo por declaração:
\(?
Essa é a primeira declaração que o computador procurará. Ela começa com um caractere de escape (\) seguido de um parêntese aberto (() seguido de um caractere opcional (?). Isso diz ao regex para procurar um parêntese aberto real para sinalizar o início de um número de telefone, mas que ele pode não estar presente em todas as instâncias de um número de telefone.
\d{3}
A segunda instrução começa com o caractere abreviado para dígito (\d) e, em seguida, tem um repetidor ({3}) que exigirá que haja 3 dígitos. Ela não termina com um ponto de interrogação porque esses três dígitos não são opcionais - eles devem estar presentes para que o resultado da pesquisa seja qualificado como um número de telefone.
\)?
Agora, o computador verificará se há um parêntese de fechamento opcional, mas, se ele não estiver presente, ainda será possível fazer a correspondência.
[- ]
Depois disso, temos uma declaração de caracteres possíveis que procurará um espaço ou um traço para corresponder.
\d{3}-\d{4}
Por fim, temos algumas declarações que esperam 3 dígitos seguidos por um traço e depois por 4 dígitos.
Você pode ver isso em ação e brincar com ele aqui: http://regex101.com/r/nW9iC5/3
Algumas coisas que você pode notar sobre essa regex é que ela só corresponderá a dois formatos aceitáveis de números de telefone:
(888) 888-8888
888-888-8888
Ele não corresponderá a vários formatos de números de telefone inaceitáveis, como, por exemplo, o número de telefone do telefone do seu celular:
8888888888
88-8888-8888
Mas isso vontade também correspondem a alguns formatos que podem não ser apropriados:
(888-888-8888
888) 888-8888
(888)-888-8888
O que você acha que poderia fazer para garantir que essa regex correspondesse apenas aos formatos apropriados?
Detalhamento de nosso URL Regex
Primeiramente, gostaria de declarar que a seguinte regex não é uma regex de correspondência de URL abrangente de forma alguma. Ele só corresponderá a um endereço da Web sem argumentos e tem vários outros problemas, mas serviria para corresponder a muitos URLs de forma eficaz.
https?:\/\/[\w-]+(\.[\w-]+)*(:\d{1,5})?
Agora vamos ao detalhamento:
https?:\/\/
Essa primeira declaração corresponde ao protocolo do URL. Como o "s" tem um ponto de interrogação depois, ele é opcional. Também há caracteres de escape na frente das barras, o que geralmente é o que precisa acontecer na regex para corresponder às barras. Portanto, na verdade, as duas únicas maneiras de um URL corresponder a essa declaração seriam começar com http://
ou https://
.
[\w-]+
Aqui temos uma declaração de caracteres possíveis seguida de um sinal de mais. Isso significa que os próximos caracteres devem ser 1 ou mais caracteres de palavras ou traços.
(\.[\w-]+)*
Aqui temos a instrução que corresponderá a um ponto final seguido de caracteres de palavras ou traços. Toda essa declaração é envolvida por parênteses e seguida por um sinal de mais, que informa ao computador que podemos repetir toda essa sequência zero ou mais vezes. Portanto, essa seção poderia corresponder a .memberpress
ou .memberpress.com
ou .memberpress.co.uk
e assim por diante.
(:\d{1,5})?
Por fim, essa declaração fornecerá um número de porta opcional a ser anexado ao final do URL, que inclui dois pontos seguidos de 1 a 5 dígitos, entre parênteses e seguido de um ponto de interrogação para tornar toda a declaração opcional.
É aqui que você pode brincar com isso: http://regex101.com/r/vL5uZ2/2
Esse regex corresponderá:
- https://memberpress.com
- https://memberpress.com
- http://localhost:3000
MAS ele não corresponderá a nenhum parâmetro no final de um URL como este:
- http://localhost:3000?test=1&page=5
O que você poderia acrescentar a essa regex para corresponder a alguns parâmetros no final de um URL?
Se você estiver interessado no regex de correspondência de URL mais abrangente (um que corresponda a parâmetros, caracteres unicode, TLDs grandes etc.) Há muitos deles que você pode consultar, mas aparentemente o mais abrangente e preciso é o criado por Diego Perini, que você pode dar uma olhada no gist do Github dele.
Detalhamento de nosso Regex de e-mail
Outro uso comum do regex é a correspondência de endereços de e-mail. Nosso regex de correspondência de e-mail realmente corresponderá a um número substancial de endereços de e-mail:
[\w\d\._%+-]+@[\w\d.-]+\.[\w]{2,4}
Aqui está o detalhamento:
[\w\d\._%+-]+
Essa declaração corresponderá a um ou mais caracteres de palavras, dígitos, pontos, sublinhados, símbolos de porcentagem, símbolos de adição ou traços.
@
Todo endereço de e-mail precisa de um símbolo "@" e é isso que corresponde a esse, é claro.
[\w\d.-]+
Após o símbolo "@", precisamos iniciar o nome do domínio. Essa declaração corresponderá a um ou mais caracteres de palavras, dígitos, pontos ou traços.
\.[\w]{2,4}
Agora precisamos fazer a correspondência com o domínio de nível superior, que é um ponto seguido de 2 a 4 caracteres de palavra.
Você também pode brincar com essa regex aqui: http://regex101.com/r/yQ2wP9/1
Mesmo que essa regex não seja 100% abrangente, ela deve ser capaz de corresponder à maioria dos endereços.
Pesquisa e substituição Regex
Portanto, em muitos casos, você se preocupará não apenas com a correspondência de padrões em seu texto com regex, mas também em utilizar o poder da pesquisa e substituição com regex.
Vamos usar o exemplo de pesquisa e substituição mencionado acima:
Pesquisar: test\.([^\.]+)\.com
Substituir: www.$1.com
Aqui está o detalhamento, começando com o padrão de pesquisa:
teste\.
Essa primeira parte corresponderá a qualquer parte da string que comece com "test".
([^\.]+)
Essa instrução corresponderá a um ou mais caracteres que sejam qualquer coisa, exceto um ponto. A declaração inteira é envolvida por parênteses por um motivo diferente do que vimos até agora: desta vez, é para salvar o que for correspondido por essa declaração para ser usado na substituição.
\.com
Por fim, ele deve corresponder a um ".com" no final.
Agora, na substituição, podemos usar "$1" para incluir tudo o que salvamos entre os parênteses no padrão de pesquisa. Se você tivesse uma segunda instrução como essa no padrão de pesquisa, poderia usá-la na substituição usando "$2".
Você pode brincar com essa pesquisa e substituir regex aqui: http://regex101.com/r/bW5vX8/1
No entanto, esse padrão de pesquisa tem algumas limitações reais. Ele só pode corresponder a URLs que começam com "test." e terminam com ".com". Como você acha que poderia modificá-lo para corresponder a URLs que terminam em ".com", ".net" ou ".org"?
Saiba mais sobre Regex
Esta cartilha lhe deu um curso intensivo sobre expressões regulares, mas há muito mais a aprender. Você pode obter mais informações sobre regex em Wikipédia ou regular-expressions.info.
Blair, o que mais gosto em suas postagens é a exclusividade dos assuntos. Atualmente, você lê sempre as mesmas coisas... todos esses artigos reescritos não se sabe quantas vezes. Leio cada uma de suas postagens porque você usa duas coisas que poucos profissionais de marketing usam: conhecimento especializado e profissionalismo. Obrigado pelas postagens interessantes e, por favor, continue assim. Todos nós precisamos de pessoas como você 🙂
Obrigado, Ivo...
Tenho um problema com formulários que prendem o usuário a um formato específico para o número de telefone. Observo que em muitos formulários de contato em que as empresas oferecem serviços técnicos a usuários internacionais, é necessário um número de telefone. Entretanto, fora dos EUA, os números de telefone podem ter formatos diferentes.
Por exemplo:
+45 8765-4321
+43 1-123-456-7890
+46 987-654-321
Em muitos casos, o usuário é forçado a fornecer um número falso para preencher o formulário. Vejamos o primeiro exemplo; coincidentemente, ele se encaixa no formato forçado típico de muitos formulários on-line. Entretanto, a pessoa que estiver lendo o formulário acreditará que o número é do Oregon e não da Dinamarca. É de se esperar que as empresas que se promovem internacionalmente estejam cientes disso. Como você lidaria com isso?
Laurence, obrigado pelo comentário... você levantou uma boa questão. Neste artigo, minha expressão regular é bastante rígida e está vinculada a números de telefone dos EUA. Mas o bom do Regex é que você pode torná-lo tão flexível ou rígido quanto quiser. Por exemplo, se eu quisesse apenas combinar números inteiros, espaços e traços possivelmente precedidos por um sinal de mais, eu poderia fazer isso:
Essa regex corresponderia a cada um de seus exemplos acima, mas é realmente liberal. Ela também corresponderá a padrões sem sentido como:
+– — — —- —
+4-9-1-2-0-1-3-0-2
600-001-001-005-3838-38-28383
Possivelmente, uma abordagem melhor seria não permitir nenhum traço, espaço ou parêntese no número se você quiser oferecer suporte a formatos internacionais. Um exemplo disso seria:
Isso corresponderia a todos os seus números acima sem traços:
+4587654321
+4311234567890
+46987654321
Essa solução seria ótima, mas também é extremamente liberal... você não teria como validar o código do país ou algo do gênero.
Outra solução possível, se você souber para quais países está direcionado, seria abordar todos os formatos possíveis que você tem interesse em suportar em sua regex, da seguinte forma:
Esse padrão corresponderia a cada um dos três exemplos acima, mas não corresponderia a nenhum número de telefone dos EUA, etc. Ele fornece uma validação melhor do que as declarações regex acima porque é mais rígido... mas também não validará nenhum número que não faça parte dos códigos de país 45, 43 e 46.
Se você pesquisar um pouco no Google, talvez encontre um regex mestre para validar números de telefone de todo o mundo. Ainda não encontrei nenhuma... portanto, se você encontrar uma, avise-me. Como alternativa, você poderia escrever sua própria regex abrangente para isso (tenho certeza de que seria bastante popular)... você só precisaria usar uma técnica como a que usei na última regex aqui... mas que engloba todos os formatos numéricos de todo o mundo. Um bom começo seria dar uma olhada em esta página na wikipedia.
De qualquer forma, espero que isso ajude... Sei que não é uma solução milagrosa, mas espero que, pelo menos, possa lhe indicar a direção certa.
Obrigado por esse artigo tão informativo e necessário. Percebo que a codificação regex é muitas vezes considerada um dado adquirido pelas pessoas que a conhecem e que, em geral, esperam que todos os outros também a conheçam. Agora, tenho um recurso compreensível ao qual posso recorrer.
Entendo que o controle de que os dígitos inseridos estejam em conformidade com um padrão predefinido é um recurso destinado a minimizar os erros. Quanto aos números de telefone internacionais em um campo de formulário, suspeito que seja mais fácil simplesmente confiar que o usuário verificará se digitou o número de telefone correto do que tentar microgerenciar o campo para as diversas possibilidades. A propósito, o uso mais importante do regex para mim foi até agora no arquivo .htaccess.
Gosto do fato de que você não apenas responde aos comentários em seu blog, mas que suas respostas são bem pensadas e significativas. Ótimo trabalho.
Obrigado, Laurence.
Ótimo argumento... mas isso faz parte da beleza do Regex. Quero dizer, você não precisa usá-la de forma alguma... mas, como eu disse na minha primeira resposta, você poderia fazer uma regex extremamente leve que apenas obrigasse a inserção de dígitos e traços ou algo assim.
Sim, usar Regex com a diretiva RedirectMatch é extremamente útil... facilita muito o mapeamento de estruturas de URL. É especialmente importante usar isso quando se está migrando um site em que todos os links serão alterados... Quero dizer, se você não usar algum tipo de mapeamento de url como o RedirectMatch, seu SEO poderá sofrer drasticamente ao migrar seu site.
Blair,
Obrigado por esta postagem! Eu sempre evito expressões regulares porque nunca dediquei tempo para entender a sintaxe. Essa postagem realmente explica e simplifica as coisas.
Não tenho mais medo de expressões regulares 🙂
Fantástico Jamie! Fico feliz por ter ajudado!