PHP e expressões regulares: o básico para iniciantes

Antecipando o início de um novo tópico no curso "Desenvolvedor de back-end em PHP" , bem como no curso relacionado "Framework Laravel" , queremos compartilhar o artigo preparado por nosso autor freelancer.

Atenção! Este artigo não é relevante para o programa do curso e será útil apenas para iniciantes . Para um conhecimento mais aprofundado, convidamos você a visitar um intensivo on-line gratuito de dois dias sobre o tópico: "Criando um bot de telegrama para pedir café em uma instituição e pagar on-line" . O segundo dia de intensa será realizado aqui .




Olá pessoal! Tudo com o próximo [20]{2,}0 ano. Hoje, quero abordar um tópico que às vezes é um tópico de piadas de "Por que você precisa aprender tudo isso se já possui soluções prontas" para "você também pode aprender tudo sobre Perl?" No entanto, o tempo passa, muitos programadores começam a dominar expressões regulares e, em Habré, não há um único artigo novo ( embora as expressões regulares não tenham mudado muito ultimamente ) sobre esse tópico. É hora de escrever outro!


Expressões regulares isoladas de sua implementação específica


Expressões regulares (indicadas em inglês como RegEx ou regex ) são uma ferramenta usada para várias opções de estudo e processamento de texto: pesquisando, verificando, pesquisando e substituindo um elemento que consiste em letras ou números (ou qualquer outro caractere em incluindo caracteres especiais e caracteres de pontuação). Inicialmente, expressões regulares chegaram ao mundo da programação a partir do ambiente da pesquisa científica, realizada nos anos 50 no campo da matemática.

Décadas depois, os princípios e idéias foram transferidos para o ambiente do sistema operacional UNIX (em particular, eles foram incluídos no utilitário grep ) e implementados na linguagem de programação Perl, que no início da Internet era amplamente usada no back-end (e até hoje é usada, mas já menos) para essa tarefa. como validação de formulário.



Se eles parecem simples, por que são tão assustadores à primeira vista?

De fato, qualquer expressão pode ser "regular" e pode ser usada para verificar ou procurar caracteres. Por exemplo, as palavras Pavel ou example@mail.ru também podem ser usadas como regulares, apenas, é claro, em uma chave bastante estreita. Para testar o desempenho de expressões regulares no ambiente PHP sem iniciar o servidor ou a hospedagem, você pode usar o seguinte serviço online (ele simplesmente não funcionou com o processamento de caracteres russos). Para iniciantes, usamos apenas Pavel como uma expressão regular.

Suponha que tenhamos o seguinte texto:

Pavel sabe demais. Pavel usando nginx e ele não é divagador.

Agora expressões regulares encontraram ambas as ocorrências da palavra Pavel. É ótimo, mas não parece muito útil (a menos que, por algum motivo, você esteja tentando analisar algo como a quantidade de menções à palavra senhor em Guerra e Paz por meio do Vim e Python, mas não tenho perguntas para você).

Variabilidade da expressão

Se sua expressão regular é variável (por exemplo, você conhece apenas uma parte dela e precisa encontrar o número de ocorrências de anos, começando em 2000 e terminando em 2099), podemos usar a seguinte expressão regular: 20 ..

Texto: Jovens escritores escrevem muitas coisas. Por exemplo, um escritor nascido em 2002 é muito diferente de 2008 e 2012.

Aqui, com a ajuda de expressões regulares, podemos encontrar todos os anos, mas até agora isso não faz sentido. Provavelmente, não precisamos de anos para além de 2012 (embora jovens escritores com menos de 8 anos de idade possam se ofender, mas não sobre isso agora). Vale a pena estudar conjuntos de caracteres, mas mais sobre isso mais tarde, porque agora falaremos sobre outra parte importante das expressões regulares: escapar de metacaracteres.

Imagine que precisamos encontrar o número de ocorrências de arquivos com a extensão .doc (suponha que exportamos apenas determinados arquivos carregados no nosso banco de dados). Mas um ponto simplesmente significa algum personagem? Então o que fazer?
Aqui, escapar de metacaracteres com uma barra invertida vem em nosso auxílio. Agora a expressão \.doc terá êxito o suficiente para procurar qualquer menção de texto com a extensão .doc :

Expressão regular: \.doc

Texto: kursach .doc , nepodozritelneyfail.exe , trabalho .doc , shaprgalka.rtf doc

Como você pode ver, podemos encontrar com sucesso o número de arquivos com a extensão .doc na lista. No entanto, não podemos extrair os nomes completos dos arquivos usando essa expressão regular, por exemplo, em uma matriz. É hora de dar uma olhada nos conjuntos de caracteres.

Corresponder um conjunto inteiro de caracteres

Em expressões regulares, a correspondência com um conjunto é fornecida usando metacaracteres - colchetes [ ] . Quaisquer dois caracteres ASII podem ser especificados como o início e o fim de um intervalo. Para uma implementação simples, suponha que desejamos encontrar todos os arquivos numerados de 0 a 9 com a extensão .jpg .

Expressão regular: [0-9]\.jpg

Texto: 1.jpg , 2.jpg , 3.jpg , photo.jpg, anime.jpg, 8.jpg , jkl.jpg

Vale ressaltar que o nome do arquivo com mais de 1 dígito não será coberto por nossa expressão regular. A escolha múltipla será um pouco menor, mas por enquanto imagine que de repente precisávamos alcançar o resultado oposto. Adicione o metacaractere ^ (que, pelo contrário, tem até duas funções em expressões regulares). Para usá-lo como uma exceção, você precisa adicioná-lo exatamente ao nosso conjunto:

Expressão regular: [^0-9]\.jpg

Texto: 1.jpg, 2.jpg, 3.jpg, phot o.jpg , anim e.jpg , 8.jpg, jk l.jpg

Mas sem múltipla escolha, essas são, obviamente, expressões inferiores.

Tabelas úteis

Aqui está uma tabela de metacaracteres:

\escapar do metacaractere como um personagem regular
^procure um caractere específico no início da linha (mas somente se você o excluir do conjunto [])
$fim de linha
|alternativa
()agrupamento
\ wtodos os caracteres alfanuméricos (por algum motivo, muitos manuais não concordam com caracteres digitais)
\ Wmesma coisa, exatamente o oposto
\ squalquer espaço em branco
\ Squalquer espaço em branco NÃO


Tabela de metacaracteres de espaço em branco
[\ b]retorno de caractere único
\ ftradução de página
\ navanço de linha
\ rretorno de carro
\ ttabulação
\ vaba vertical


Múltipla escolha: tornando a validação simples


Armado com o conhecimento adquirido, tentaremos fazer uma expressão regular que encontre, por exemplo, palavras menores que 3 letras (uma tarefa padrão para anti-spam). Se tentarmos usar a seguinte expressão regular - \w{1,3} (na qual o metacaractere \w indica qualquer caractere, e colchetes indicam o número de caracteres de quantos a quantos, destacaremos todos os caracteres seguidos - você precisa designar de alguma forma início e fim das palavras no texto, para isso precisamos do metacaractere \b .

Expressão regular: \b\w{1,3}\b:

Texto: boa palavra
não
ovo

Nada mal! Agora, palavras com menos de três letras não poderão entrar no nosso banco de dados. Vejamos a validação do endereço para correspondência:

Expressão regular: \w+@\w+\.\w+

Requisitos: no email no início deve haver qualquer caractere (números ou letras, porque o email, que consiste apenas de números no início, é bastante comum). Em seguida, vem o símbolo @ , em seguida, quantos caracteres você desejar, seguidos por um ponto de escape (ou seja, apenas um ponto) e um domínio de primeiro nível.

Considere a repetição de caracteres com mais detalhes.

Agora, vamos dar uma olhada em como repetir caracteres em expressões regulares. Por exemplo, você deseja encontrar qualquer combinação de números de 2 a 6 no texto:

Expressão regular: [2-6]+

Texto: Aqui estão os 89 diferentes 234 dígitos de 24 .

Deixe-me dar uma tabela de todos os quantificadores de metacaracteres:

*caracteres repetem 0 e ad infinitum
+repetido de 1 até o infinito
{n}repita exatamente n vezes
{n,}de n ao infinito
{n1, n2}de n1 a n2 vezes exatamente
?0 ou 1 caractere, não mais


Não há nada complicado em aplicar quantificadores. Exceto por uma ressalva: quantificadores gananciosos e preguiçosos. Aqui está a tabela:

**?
++?
{n,}{n,}?


Os quantificadores preguiçosos diferem dos gananciosos, pois capturam o número mínimo, e não o máximo, de caracteres. Imagine que temos a tarefa de encontrar todas as tags de título h1-h6 e seu conteúdo, e o restante do texto não deve ser afetado (eu deliberadamente inseri a tag h7 inexistente para não sofrer escape das tags Habré):

Expressão regular: <h [1-7]>. *? <\ / H [1-7]>

Texto: < h7 > olá </ h7 > lorem ipsum avada kedavra < h7 > compre < /h7 >

Tudo funcionou com sucesso, mas apenas graças ao quantificador preguiçoso. No caso de usar o quantificador ganancioso, todo o texto entre as tags se destacaria (acho que isso não precisa de uma ilustração).

Bordas da cadeia de caracteres

Os limites das cadeias de caracteres que já usamos acima. Aqui está uma tabela mais detalhada:

\ blimite de palavras
\ Bnão limite de palavras
\ Ainício da linha
\ Zfim de linha
\ Gfim de ação


Trabalhar com subexpressões

Subexpressões em expressões regulares são feitas usando o metacaractere de grupo () .
Aqui está um exemplo de uma expressão regular que pode encontrar universalmente várias variações de endereços IP.

Expressão regular: (((25 [0-5]) | (2 [0-4] \ d) | (1 \ d {2}) | (\ d {1,2})) \.) {3} (((25 [0-5] | (2 [0-4] \ d) | (1 \ d {2}) | (\ d {1,2}))))]

Texto: 255.255.255.255 é apenas um endereço
191.198.174.192 wikipedia
87.240.190.67 vk
31.13.72.36 facebook

Ele usa o operador lógico | (ou) que nos permite compor uma expressão regular que corresponda à regra pela qual os endereços IP são compilados. O endereço IP deve conter de 1 a 3 dígitos, nos quais um número de três números pode começar com 1, com 2 (ou então o segundo dígito deve estar entre 0 e 4) ou iniciar com 25 e, em seguida, 3 dígitos acaba por estar entre 0 e 5. Além disso, deve haver um ponto entre cada combinação de números. Usando as tabelas acima, tente decifrar a expressão regular na parte superior. Expressões regulares no começo assustam você com suas expressões longas, mas longas não significa complexo.

Olhe para frente

Para visualizar uma expressão para qualquer combinação de determinados caracteres, um padrão é indicado pelo qual uma correspondência é detectada, mas não retornada. Essencialmente, olhar para o futuro define uma subexpressão e, portanto, é formada de acordo. O padrão de sintaxe para o futuro consiste em uma subexpressão precedida por? =, E o texto a ser correspondido é seguido igualmente.

Aqui está uma tarefa específica: existe uma senha que deve consistir em pelo menos 7 caracteres e necessariamente incluir pelo menos uma letra e número em maiúsculas. Aqui tudo será um pouco mais complicado, porque o usuário poderá colocar a letra maiúscula no início e no meio da frase (e a mesma coisa deve ser repetida com a letra).

Portanto, precisamos aguardar a expressão. Além disso, precisamos dividir os sinais em grupos. E eu quero limitar seus tamanhos de 8 a 22 caracteres:

Expressão regular: /^(?=.*[az])(?=.*[AZ])(?=.*\d)[a-zA-Z\d]{8,}$/

Texto: Qwerty123
Im789098
password fraca

Características do trabalho de expressões regulares em PHP


Para aprender como expressões regulares funcionam em PHP, consulte as funções na documentação oficial do PCRE (Expressões Regulares Compatíveis com Perl), disponível no site oficial. A expressão deve estar entre delimitadores, por exemplo, em barras.

Caracteres arbitrários podem ser um delimitador, exceto alfanumérico, barra invertida '\' e zero byte. Se o caractere delimitador aparecer no padrão, ele deverá ser escapado \. Como separadores, as combinações vêm de Perl: (), {}, [].

Quais funções são usadas no php? O pacote PCRE fornece os seguintes recursos para suportar expressões regulares:

  • preg_grep () - Executa uma pesquisa e retorna uma matriz de correspondências.
  • preg_match () - pesquisa a primeira correspondência usando expressões regulares
  • preg_match_all () - Executa uma pesquisa global usando expressões regulares
  • preg_quote () - pega um modelo e retorna sua versão escapada
  • preg_replace () - executa uma operação de pesquisa e substituição
  • preg_replace_callback () - também realiza uma operação de pesquisa e substituição, mas eles usam retorno de chamada - uma função para qualquer substituição específica
  • preg_split () - divide uma sequência de caracteres em substrings


O modificador i para organizar correspondências sem distinção entre maiúsculas e minúsculas.
Usando o modificador m , você pode ativar o modo de processamento de texto com várias linhas.

A substituição de strings pode ser calculada como código PHP. Para ativar este modo, use o modificador e .

Todas as preg_split() preg_replace() , preg_replace_callback() e preg_split() suportam um argumento adicional, que introduz restrições no número máximo de substituições ou partições.

Backlinks podem ser indicados pelo sinal $ (por exemplo, $ 1) e, nas versões anteriores, os sinais \\ são usados ​​no lugar do sinal $.
Os metacaracteres \ E, \ l, \ L, \ u e \ U não são usados ​​(portanto, não foram mencionados neste artigo).

Nosso artigo ficaria incompleto sem as classes de caracteres POSIX, que também funcionam em PHP (e, em geral, podem aumentar a legibilidade de seus regulares, mas nem todos estão com pressa de aprender, porque frequentemente quebram a lógica da expressão).

[[: alnum:]]Qualquer letra do alfabeto ou número em inglês
[[: alpha:]]Qualquer letra ([a-zA-Z])
[[: em branco:]]Espaço em branco ou código de caractere 0 e 255
[[: dígito:]]Qualquer dígito ([0-9])
[[: inferior:]]Qualquer letra minúscula do alfabeto inglês ([az])
[[: superior:]]Qualquer letra maiúscula do alfabeto inglês ([AZ])
[[: punct:]]Qualquer sinal de pontuação
[[: espaço:]]Qualquer espaço em branco
[[: xdigit:]]Qualquer dígito hexadecimal ([0-9a-fA-F])


No final, darei um exemplo de uma implementação concreta de expressões regulares em PHP, usando as implementações mencionadas acima. Também adicionei a validação do nome de usuário para que ele não pudesse inserir combinações muito curtas de letras (bem, suponha que sejam apelidos, não nomes, nomes menores que duas letras):

  $pattern_name = '/\w{3,}/'; $pattern_mail = '/\w+@\w+\.\w+/'; $pattern_password = '/^(?=.*[az])(?=.*[AZ])(?=.*\d)[a-zA-Z\d]{8,}$/'; if (preg_match($pattern_name, $name) && preg_match($pattern_mail, $mail) && preg_match($pattern_password, $_POST['password'])) { #  ,  ,   ,   ,      } 


Obrigado a todos pela atenção! É claro que hoje abordamos apenas uma parte das expressões regulares e mais alguns artigos podem ser escritos sobre elas. Por exemplo, não falamos sobre a implementação da busca por repetições de palavras idênticas no texto. Mas espero que o conhecimento adquirido seja suficiente para escrever de maneira significativa minha primeira validação de formulário e só então passar para coisas mais furiosas.

Por tradição, alguns links úteis:

Folha de dicas para expressões regulares do MIT
A parte oficial da documentação do php regex.

Só isso. Vejo você no intensivo !
O segundo dia de intensa será realizado aqui

Source: https://habr.com/ru/post/pt484048/


All Articles