Como você aprende Expressões Regulares? [fechadas]

80

Eu não estou pedindo onde aprenda. Eu encontrei muitos bons recursos on-line e livros, etc.

Mas como diabos eu lidei com eles. Onde está o começo disso, o fim? Quando o processador regexp avança no texto, quando ele mantém sua posição e tenta outra correspondência? etc.

Tenho vontade de descobrir hieróglifos nas pirâmides egípcias.

    
por dumbBoy 17.04.2014 / 22:33
fonte

18 respostas

67

Acho que o conhecimento da Teoria do Automata é fundamental para o entendimento.

Depois de entender o que é um autômato e como os idiomas comuns são definidos, entenda o expressões regulares será muito mais fácil.

Quanto à sintaxe e diferenças específicas entre as várias implementações ... Bem, algumas coisas você só precisa lembrar. Existem auxílios para isso também.

Editar

Alguns dos comentários abaixo levantaram pontos importantes:

  1. Não esqueça que as expressões regulares (como implementadas na maioria das linguagens de programação) são um superconjunto de expressões regulares na teoria dos autômatos. Embora uma boa base teórica seja um lugar útil para começar, não lhe dirá tudo. (Obrigado, David Thornley)

  2. Vários comentadores dizem que é possível aprender as várias sintaxes de regex sem aprender a base teórica. Embora seja verdade que você possa aprender a sintaxe sem entender completamente como isso funciona, foi minha impressão que o entendimento completo é o que o OP buscava. A questão era sobre a base real: quando o processador avança? Quando isso pára? Como decide que é um jogo? Essa é a base, essa é a teoria, e é baseada na Teoria do Automata. Claro, você pode dirigir um carro sem saber como o motor funciona. Mas se você está sendo perguntado "como o gás realmente o faz dirigir" - você tem que falar sobre como o motor é construído, não é?

por 18.04.2014 / 01:26
fonte
36

praticando.

Aprendi me divertindo com o web scraping. Tenho certeza de que não estava sozinho fazendo isso apenas por diversão.

Um exemplo: Escreva um código que recupere o futebol mais recente, e que o tênis (o esporte que você gosta de fato) obtenha no seu site de esportes favorito. Faça isso escrevendo algum código para carregar a página, extraia as pontuações com expressões regulares e imprima-as no console ou em algum arquivo de texto. Certifique-se de que, com a expressão regular escolhida, você recupere apenas as pontuações e nada mais. Às vezes isso pode ser bastante desafiador: -)

Segundo exemplo: Escreva algum código que recupere a imagem da sua webcomic favorita, (eu gosto muito Sinfest por exemplo) e que armazena em algum lugar no seu disco rígido. Use apenas expressões regulares para recuperar a tag "img" e seu conteúdo. Opcionalmente, também recupere seu título se estiver armazenado em algum lugar.

    
por 25.09.2011 / 12:18
fonte
23

Eu sei que você não está pedindo recursos, mas Dominando Expressões Regulares por Jeffrey EF Friedl foi como eu aprendi como eles funcionam e como usá-los. Mesmo depois de chegar ao ponto de usar muitos deles para analisar coisas diferentes, o primeiro capítulo tinha coisas novas para mim.

Você quer entender esses malditos regexp? Leia este livro.

    
por 23.09.2011 / 09:41
fonte
19

Where is the start of it, the end? When does the regexp processor advance on the text, when does it hold its stand and tries another match? etc.

Gostaria de começar por esclarecer os seus objetivos e, em seguida, descobrir o seu estilo de aprendizagem .

O que me impressionou na sua pergunta é que você pergunta "como eu aprendo expressões regulares?" e, em seguida, siga imediatamente com a pergunta "como funciona o mecanismo de expressão regular internamente?" Você parece estar insinuando que essas duas coisas têm algo a ver uma com a outra, o que é um ponto importante. Talvez você seja uma pessoa que aprenda como algo funciona desmontando ou construindo você mesmo.

Para aplicativos iniciantes, geralmente não há necessidade de entender como uma ferramenta funciona para usá-la efetivamente. Você não precisa saber como funciona um motor de perfuração para colocar buracos na madeira; você precisa entender como usar a broca, não como construir uma broca.

Então, qual é o seu objetivo? Você pretende aprender a criar um mecanismo de expressões regulares? ou pretende aprender a usar expressões regulares para resolver problemas de negócios? Atingir esses objetivos diferentes provavelmente requer diferentes técnicas de aprendizagem.

Para resolver sua dúvida específica sobre como o mecanismo de expressão regular funciona: depende. A abordagem teórica "clássica" para expressões regulares é usar a expressão regular como um modelo para um autômato finito não determinístico, em seguida, construir o autômato finito determinístico equivalente e, em seguida, executar esse autômato contra a entrada.

Quase ninguém realmente faz isso por vários motivos. Primeiro, o número de estados multiplicado pelo número de caracteres de entrada possíveis produz uma tabela de transição de estado que é enorme até mesmo para pequenas expressões regulares. Claro, a maior parte disso pode ser compactada, mas ainda assim, há muitas regras de transição. Em segundo lugar, outras abordagens são geralmente mais rápidas. Em terceiro lugar, as chamadas expressões "regulares" estão nas bibliotecas regexp modernas, nada disso. Eles não são idiomas regulares ; eles são geralmente reconhecidos por autômatos de empilhamento, não por linguagens autómatas finitas.

(Eu comecei a escrever uma longa série sobre como tudo isso funciona, mas fiquei sem energia depois que apenas o primeiros doze artigos . Você pode achá-los interessantes se você quiser uma breve introdução sobre os fundamentos teóricos das expressões regulares básicas.)

Os motores de expressão regular real normalmente usam uma estratégia de retrocesso. O mecanismo de expressão regular que criamos para o mecanismo JScript há mais de uma década compila agora a expressão regular em uma linguagem bytecode que inclui primitivas para reconhecer sequências e retroceder para estados anteriores. Nós então construímos um intérprete para essa linguagem de bytecode.

Eu não tentaria entender como um mecanismo regexp funciona antes de ter uma compreensão bastante sólida de como usar expressões regulares. Concentre-se nisso antes de começar a investigar as estratégias de otimização de vários mecanismos diferentes.

    
por 22.09.2011 / 19:06
fonte
6

How the heck do I tackle them?

Como qualquer coisa nova:

10 Study
20 Practice
30 goto 10

Estudo

Eu acho que os professores mais bem sucedidos começam a ensinar qualquer assunto, primeiro fornecendo um pouco de fundo para o assunto. É importante ter um contexto do que você está aprendendo e, mais importante, por que você está aprendendo.

É toda correspondência de string

Expressões regulares são um meio de correspondência de padrões no texto. É uma linguagem declarativa, incorporada em várias outras linguagens de programação.

Gostaria de enfatizar que é uma linguagem declarativa, expressões regulares são úteis para expressar o que corresponde, mas elas não expressam de forma alguma como o programa é fazer a correspondência. Por essa razão, é possível usar expressões regulares muito rapidamente e muito lentamente na mesma linguagem de programação simplesmente usando um analisador RegEx diferente.

O motivo para a criação de expressões regulares é o mesmo para a criação da maioria das linguagens de programação: os programadores viram-se repetidamente executando a mesma tarefa complicada e decidiram que queriam uma maneira mais simples de escrever o código.

Alguns vão (e devem) queixar-se da minha sentença anterior dizendo algo como:

O RegEx não simplifica o programa.

é verdade

RegEx não torna qualquer programa mais simples, o RegEx torna a escrita mais simples do programa. Você ainda precisa ser minucioso em seus testes para ter certeza de que todos os casos corretos são correspondidos corretamente, e todos os casos incorretos não são. É realmente difícil testar "todos" e, com padrões complicados, é realmente difícil testar "a maioria". Na pior das hipóteses, você ainda deve estar testando "alguns" casos.

permite incorporar alguns exemplos Eu obrigatoriamente escolhi o mecanismo RegEx do JavaScript porque eu posso testá-lo ao vivo no navegador facilmente e porque eu não precisarei fazer nenhuma string escapando enquanto uso os literais do RegEx.

Quando você faz uma correspondência de string normal, testa um valor de string em relação a outro. Eles podem vir de qualquer lugar, mas no final são duas strings comparadas umas contra as outras:

if ( 'foo' == 'bar' ) doSomething();

Esse exemplo é uma droga porque nunca fará qualquer coisa

if ( foo == 'bar' ) doSomething();

Muito melhor; agora, na verdade, não sabemos de antemão se algo será ou não feito. Agora podemos começar a aceitar a entrada do usuário:

if ( prompt( 'Say "bar" to do something.' ) == 'bar' ) doSomething();

Maravilhoso, agora os usuários podem inserir bar e algo acontecerá, até você receber relatórios de bugs dos usuários dizendo que "bar" não está funcionando ou que "BAR" não está funcionando ou que eles digitaram BRA 100 vezes e nada acontece.

Ignorando os erros de ortografia e caracteres extras, 'bar' != 'BAR' e os programadores precisam pensar em uma maneira de testar onde os caracteres estão no caso errado.

Solução simples, use toLowerCase . Isso funciona maravilhosamente, mas e os nossos usuários que estão usando o inglês britânico sobre o inglês americano quando você está combinando something == 'color' ? Agora você terá que combinar something == 'color' || somthing == 'colour' .

Longa história curta, padrões simples se transformam em muito código repetitivo muito rapidamente.

O exemplo de cor pode ser simplesmente combinado com:

/colou?r/.test( something )

uma sólida compreensão das noções básicas de expressões regulares pode reduzir significativamente a quantidade de tempo que você desperdiça reinventando a roda.

Onde estudar

A maioria dos idiomas que implementam expressões regulares tem pelo menos um recurso disponível para a sintaxe específica do uso de expressões regulares nesse idioma. Um para JavaScript pode ser encontrado no MDN

leia.
tudo isso.
então leia de novo.

Leva tempo para aprender, pense nisso como um investimento: uma hora para aprender o RegEx agora salva uma hora na próxima vez que você precisar fazer uma correspondência de padrão de string e depois outra hora na próxima vez.

Pratique

Depois de ler tudo sobre o RegEx, você provavelmente não entenderá a maior parte dele. Isso porque você não está de fato fazendo qualquer coisa com ele.

Mencionei porque escolhi o JS para este exemplo, peço-lhe para mexer com ele no seu navegador. É rápido e você pode fazer isso na sua barra de URL.

JS tem algumas maneiras diferentes e simples de usar o RegEx:

string.match( regex )
regex.exec( string )
regex.test( string )

Começando com algo simples como:

javascript:'color'.match(/colou?r/);

é uma maneira fácil de colocar o pé na porta. Brinque com ele, quebre, veja o que combina e o que não funciona.

Quando você ficar preso na prática, continue com 30 . Você precisa ler para aprender mais, mas precisa praticar para entender verdadeiramente o que aprendeu.

    
por 23.09.2011 / 03:36
fonte
5

Brian Kernighan escreve um processador reg-ex simples no livro Beautiful Code . Percebo que você não está procurando por recursos, mas pode ajudar a ver uma implementação básica , por dentro.

    
por 22.09.2011 / 13:30
fonte
4

No desenvolvimento normal, o código de depuração pode fornecer informações muito úteis. Expressões regulares não são diferentes. Portanto, correndo o risco de soar como um anúncio, obtenha RegexBuddy . Ele tem uma ótima ferramenta para exibir visualmente o que o mecanismo está fazendo enquanto manipula sua expressão e a string de entrada.

    
por 22.09.2011 / 19:23
fonte
3

Expressões regulares podem se tornar muito complicadas muito rapidamente, então eu recomendo que você comece a aprender usando tutoriais. Saiba que a forma mais simples de expressão regular é uma string representando o que você está procurando. Infelizmente, para poder definir regras de pesquisa especiais, são necessários determinados caracteres, e esses caracteres devem ter escape ou você estaria criando uma expressão regular inválida ou incorreta.

Meu conselho é começar com um exemplo de algo que você está procurando e escapar dela. Em outras palavras, se você estiver procurando por algo entre parênteses, dê um exemplo de uma dessas sequências no texto em que está pesquisando: (this is an example of something you'd want to find)

Comece por escapar caracteres para pesquisar o caractere literal: \(this is an example of something you'd want to find\)

Teste-o, verifique se ele encontra seu exemplo corretamente. Em seguida, generalize a expressão para encontrar qualquer texto desse tipo, não apenas o exemplo encontrado. Então, seria então: \([^)]*\) (significa qualquer caractere que não seja ")" para qualquer número de ocorrências, incluindo 0).

Teste-o novamente e verifique se ele não apenas encontra seu exemplo, mas outros também. Procure por expressões regulares mais complicadas, porém mais freqüentes, na internet, e corrija-as com suas expressões regulares existentes para evitar ter que se preocupar com todas as possibilidades.

É sobre isso. E oh, aprenda e ame \ Q ... \ E. Na maioria das linguagens de expressões regulares, \ Q indica o início de um padrão literal e \ E marca o fim, caso você tenha que lidar com padrões particularmente sofisticados e não saiba como escapar deles. Isso salvou minha vida mais do que algumas ocasiões.

    
por 22.09.2011 / 12:31
fonte
3

Eu vou te dar uma resposta simples para uma pergunta simples. Primeiro, você precisa entender o que são Expressões Regulares (RegEx) - o que elas fazem, para que são usadas. Então, uma ótima ferramenta para começar.

  1. O que é isso? RegEx é uma linguagem para expressar correspondência de padrões. Ou seja, usando-o, você pode criar uma combinação de caracteres que reconheça ou encontre padrões no texto. Como isso é útil? Na programação, você pode dizer aos computadores para combinar o texto de alguma fonte (uma entrada do usuário, uma página da web, etc.) e detectar se padrões de texto específicos estão ou não contidos nela. Por exemplo, um ponto (.) Representa qualquer caractere - letra ou número. Os números entre chaves representam números de iterações, então ". {1,30}" indica qualquer caractere, repetido entre 1 e 30 vezes - em outras palavras, você não pode ter uma string vazia e não pode ser maior que 30 personagens. E continua a partir daí.

  2. Como começar a aprender? A melhor ferramenta absoluta que já vi é o Expresso , mas é apenas para o Windows. Ele tem uma GUI muito extensa, na qual você clica nos elementos que deseja adicionar à sua expressão e, em seguida, um testador verifica a entrada em várias entradas para ver os resultados. Eu não vi nada de bom no Mac (mas estou executando o Windows no VMWare, então não preciso de uma versão para Mac), não passei muito tempo procurando no Linux.

por 22.09.2011 / 20:24
fonte
3

Além de uma boa referência, o modo como você realmente aprende é usar boas ferramentas de aprendizado. Um deles é o uso do editor de código-fonte aberto Vim , com duas opções definidas:

  1. : defina incsearch ... conforme você digita em um padrão de pesquisa na linha de comando, o editor on-the-fly vai para a primeira parte do texto que corresponde e realça exatamente o que está correspondendo. Se você digitar algo que faz com que ele não corresponda mais a nada, o Vim pula o cursor de volta para onde você estava quando começou.
  2. : defina hlsearch ... isso diz ao Vim para mostrar um fundo realçado em todo o texto que corresponde à pesquisa RE atual.

O outro é usar uma chamada de ferramenta gratuita RegExCoach . Você cola no texto que deseja pesquisar e, em outra janela, desenvolve sua expressão regular. Como o Vim, ele destaca os jogos de sucesso na hora.

    
por 22.09.2011 / 20:59
fonte
2

Você começa com uma comparação básica de string. Muito fácil, mas também não tão poderoso.

Em seguida, pode ter ocorrido a você, que você precisa de comparações insensíveis, para que "grego" e "GreeK" sejam iguais. Isso é um pouco mais poderoso.

Um dia você percebe que pequenas diferenças na ortografia não devem impedir que duas palavras comparem entre si: ou seja, "organize" e "organize" deve ser igual. Você senta e escreve algum código que faz isso e você está feliz.

Até você abstrair um pouco mais e perceber que às vezes você quer que todas as palavras que terminam em "ize" se comparem com seus irmãos em ortografia britânica. Ou, repetições de algumas cordas uma certa quantidade de vezes. E, claro, você precisa combinar tudo isso.

E assim por diante. Finalmente, você provavelmente terminará com alguma notação em que nem todos os personagens se identificam. Nada mais é um regexp. Pode-se ver isso como descrição de um conjunto de strings.

E, em seguida, é bastante fácil e resume-se aos seguintes 3 princípios básicos:

Você tem regexps básicos: caracteres que representam eles mesmos, classes de caracteres, abreviações úteis e não tão úteis para classes de caracteres como \ d ou \ p {Lu} para letras maiúsculas.

E então, você tem algumas possibilidades de combiná-las: se r1 e r2 são regexps, então também são r1r2 r1 | r2 (r1).

Por último, mas não menos importante, os modificadores de repetição: r? r * r + r {n, m}

Isso é o máximo que você precisa saber. Qualquer outra coisa que você possa procurar quando precisar.

    
por 22.09.2011 / 13:17
fonte
2

Duas boas outras respostas dizem para você aprender a teoria por trás dos regexes e para praticar, que são ótimos conselhos. Também recomendo obter uma boa ferramenta de regex visual para ajudá-lo se você for sério.

RegexBuddy , por exemplo, tem um modo de depuração visual que permite percorrer a execução de uma regex e mostra, por meio de destaques e texto explicativo, o que o mecanismo regex está fazendo em cada etapa. Há um vídeo que demonstra essa depuração em seu site.

    
por 22.09.2011 / 19:03
fonte
2

Tudo o que podemos oferecer a você é mais recursos para aprender. Esta questão é em si um recurso.

A propósito, aprendi expressões regulares com bastante facilidade neste site: link

    
por 22.09.2011 / 21:40
fonte
1

Para mim, ver o que o regexp está correspondendo à medida que estou construindo ajuda muito a facilitar minha vida e ajudou-me a compreendê-los melhor.

Para fazer isso, abrirei um arquivo com o texto de destino no Emacs e, em seguida, use o comando isearch-forward-regexp . Quando você digita o regexp, o Emacs mostra o que ele está combinando (essa é a parte "isearch").

Para executar o comando, no Emacs, você pode usar <ESC>xisearch-forward-regexp .

    
por 22.09.2011 / 22:38
fonte
1

Eu aprendi expressões regulares aprendendo flex e bison, que são usadas para construir analisadores lexicais e parsers. Você não poderia ter um analisador sem expressões regulares, e o livro é incrivelmente bom em percorrer o caminho teoria sem se mover muito rápido.

Fundamentalmente, praticamente todos os motores de regex atualmente seguem os mesmos princípios. Eles são todos máquinas de estados finitos e se você realmente gostar disso, então você tem uma vantagem sobre praticamente qualquer código que você escreve. É semelhante ao aprendizado da recursão em que, uma vez obtido, você aplica os problemas instintivamente. Eles são fáceis de resolver com a ferramenta certa, mas muito difícil sem ela.

Outra coisa sobre o aprendizado do lexx e do yacc, em comparação com as expressões regulares, é que você aprende como eles funcionam internamente. Como o programa olha para frente, por que termina uma correspondência, como contém os dados e muito mais. Compreender os ponteiros é uma necessidade absoluta, mas se você conseguir o lexx e o yacc e passar por ele desde o início, aprenderá tudo o que pediu e terá uma ferramenta altamente poderosa para o resto de sua carreira.

Esta pergunta inclui um monte de recursos para aprender e um esqueleto flexível que eu joguei juntos.

    
por 23.05.2017 / 14:40
fonte
1
Mais uma vez, eu primeiro tento me certificar de que não há uma maneira mais fácil de resolver o problema / "tokenize" a string.

Quando você não consegue encontrar um, eu vejo como um problema não tentar combinar o que você quer com a string, mas sim NÃO combinar com o que você não quer. Isso ocorre principalmente porque os regexs são gananciosos. Mas serviu-me bem como uma abordagem para conseguir o que eu quero.

Veja um exemplo:

string = "Sep 22 19:57:38 host fcron[9137]: \
          Job fbsetbg -r $HOME/backgrounds/ \
          started for user user (pid 9138)"

para corresponder ao minuto:

string.match /^\w+\s\d+\s\d+:(\d+):\d+\s\w+\s/ # correct but bad
string.match /\d+:([^:]+):\d+/                 # correct and good

Em vez de tentar encontrar o tempo junto com todo o resto, tente encontrar os limites distintos.

O exemplo é um pouco inventado, mas tudo o que consegui criar.

    
por 23.09.2011 / 05:18
fonte
1

Uma abordagem que usei foi encontrar um monte de projetos de código aberto que precisavam de atualizações de sintaxe e depois escrever um script sed cada vez mais complexo, que era composto de muitas expressões regulares.

O script precisava ser executado em vários arquivos diferentes em cada projeto de código aberto. Em seguida, corra contra muitos projetos diferentes com estilos diferentes. Eu comecei com algo muito simples como %s/before/after , então eu achei que correspondia a muitos casos. então eu adicionei mais coisas para evitar isso. Então eu encontrei diferentes projetos usando diferentes estilos de sintaxe que precisavam de mudanças diferentes.

No final, acabei com

  • grandes habilidades e conhecimento sobre expressões regulares
  • boas habilidades com sed
  • ajudando muitos projetos de código aberto
  • recebendo muita atividade de contribuição exibida no perfil do meu github
  • outra boa ferramenta 'swiss-army knife' para o virtual toolbelt

e foi ajudado nesta abordagem pela necessidade de

  • atinja metas reais sem trapacear
  • use as habilidades (regex) como parte de um objetivo maior com maior motivação.
  • conseguir comprovar as habilidades que aprendi alterando o código de outras pessoas e, em seguida, revisando as alterações.

Também transmitirei que há vários sites para os vários idiomas - ruby, javascript, etc., que permitem que você brinque com expressões e textos de amostra para gratificação imediata. Estes são:

regexes em vários idiomas em um site

  • link javascript / php / python
  • link PHP / JAVA / JS / ASP / .NET / C # / VB.NET

concentre-se nos grupos de correspondências:

por 18.04.2014 / 01:28
fonte
0

Descobri que aprender expressões regulares é semelhante ao aprendizado das tabelas de multiplicação - sim, você precisa entender as ideias por trás delas, mas, no final das contas, basta fazer isso com frequência e repetidamente.

Quando eu estava aprendendo, eu tinha como meta fazer alguns exercícios de regex por dia. Na prática, isso significava pelo menos uma vez por dia, eu tentava olhar para uma seqüência de caracteres ou texto na minha tela e chegar a um desafio - "posso obter todos os endereços de e-mail fora daqui", ou "encontrar todos os ocorrências da palavra "código" usado como um verbo em vez de um substantivo, "coisas assim.

Fazer isso por algumas semanas realmente valeu a pena - e, é claro, revisões e atualizações periódicas são necessárias. Estou prestes a ter um.

Também achei essa ferramenta on-line útil, já que posso testar a regex em tempo real: link

    
por 23.09.2011 / 03:09
fonte