Existe uma razão específica para a baixa legibilidade do design da sintaxe da expressão regular?


160

Todos os programadores parecem concordar que a legibilidade do código é muito mais importante do que as one-liners de sintaxe curta que funcionam, mas exigem que um desenvolvedor sênior interprete com algum grau de precisão - mas essa parece ser exatamente a maneira como as expressões regulares foram projetadas. Havia uma razão para isso?

Todos concordamos que selfDocumentingMethodName()é muito melhor que e(). Por que isso não se aplica a expressões regulares também?

Parece-me que, em vez de projetar uma sintaxe da lógica de uma linha sem organização estrutural:

var parse_url = /^(?:([A-Za-z]+):)?(\/{0,3})(0-9.\-A-Za-z]+)(?::(\d+))?(?:\/([^?#]*))?(?:\?([^#]*))?(?:#(.*))?$/;

E isso nem é uma análise rigorosa de um URL!

Em vez disso, poderíamos tornar uma estrutura de pipeline organizada e legível, para um exemplo básico:

string.regex
   .isRange('A-Z' || 'a-z')
   .followedBy('/r');

Que vantagem a sintaxe extremamente concisa de uma expressão regular oferece, além da menor operação possível e da sintaxe lógica? Por fim, existe uma razão técnica específica para a baixa legibilidade do design da sintaxe de expressão regular?


Comentários não são para discussão prolongada; esta conversa foi movida para o bate-papo .
Maple_shaft

1
Eu tentei resolver exatamente esse problema de legibilidade com uma biblioteca chamada RegexToolbox. Até agora, é portado para C #, Java e JavaScript - consulte github.com/markwhitaker/RegexToolbox.CSharp .
Mark Whitaker

Muitas tentativas foram feitas para resolver esse problema, mas é difícil mudar a cultura. veja minha resposta sobre expressões verbais aqui . As pessoas buscam a menor ferramenta comum disponível.
Parivar Saraff

Respostas:


178

Há uma grande razão pela qual as expressões regulares foram projetadas da maneira mais concisa possível: elas foram projetadas para serem usadas como comandos para um editor de código, não como uma linguagem para codificar. Mais precisamente, edfoi um dos primeiros programas a usar expressões regulares , e a partir daí expressões regulares começaram sua conquista pelo domínio do mundo. Por exemplo, o edcomando g/<regular expression>/plogo inspirou um programa separado chamado grep, que ainda está em uso hoje. Por causa de seu poder, eles foram posteriormente padronizados e usados ​​em uma variedade de ferramentas como sedevim

Mas o suficiente para as trivialidades. Então, por que essa origem favoreceria uma gramática concisa? Porque você não digita um comando do editor para lê-lo mais uma vez. Basta que você se lembre de como montá-lo e que possa fazer as coisas com ele que deseja fazer. No entanto, cada caractere que você precisa digitar diminui o andamento da edição do arquivo. A sintaxe da expressão regular foi projetada para escrever pesquisas relativamente complexas de maneira descartável, e é exatamente isso que dá às pessoas dores de cabeça que as usam como código para analisar algumas entradas de um programa.


5
regex não se destina a analisar. caso contrário, stackoverflow.com/questions/1732348/… . e dores de cabeça.
Njzk2

19
@ njzk2 Essa resposta está realmente errada. Um documento HTML não é uma linguagem comum, mas uma tag aberta HTML , que é o que a pergunta faz, na verdade é.
usar o seguinte código

11
Essa é uma boa resposta para explicar por que o regex original é tão enigmático quanto é, mas não explica por que não existe atualmente um padrão alternativo com maior legibilidade.
Doc Brown

13
Então, para aqueles que pensam que grepé uma "garra" mal pronunciada, ela vem de fato de g/ re(para expressão regular) / p?
Hagen von Eitzen

6
@DannyPflughoeft Não, não. Uma tag aberta é apenas <aaa bbb="ccc" ddd='eee'>, não há tags aninhadas dentro dela. Você não pode aninhar tags, o que aninha são elementos (tag aberta, conteúdo incluindo elementos filho, tag close), que a pergunta não estava perguntando sobre a análise. As tags HTML são uma linguagem comum - o balanceamento / aninhamento ocorre em um nível acima das tags.
usar o seguinte código

62

A expressão regular que você cita é uma bagunça terrível e acho que ninguém concorda que seja legível. Ao mesmo tempo, grande parte dessa feiura é inerente ao problema que está sendo resolvido: existem várias camadas de aninhamento e a gramática da URL é relativamente complicada (certamente muito complicada para se comunicar de maneira sucinta em qualquer idioma). No entanto, certamente é verdade que existem maneiras melhores de descrever o que esse regex está descrevendo. Então, por que eles não são usados?

Um grande motivo é a inércia e a onipresença. Ele não explica como eles se tornaram tão populares em primeiro lugar, mas agora, quem conhece expressões regulares pode usar essas habilidades (com muito poucas diferenças entre os dialetos) em centenas de idiomas diferentes e mais mil ferramentas de software ( por exemplo, editores de texto e ferramentas de linha de comando). A propósito, os últimos não usariam nem poderiam usar nenhuma solução que equivale a escrever programas , porque são muito usados ​​por não programadores.

Apesar disso, as expressões regulares são frequentemente usadas demais, ou seja, aplicadas mesmo quando outra ferramenta seria muito melhor. Não acho que a sintaxe do regex seja terrível . Mas é claramente muito melhor em padrões curtos e simples: o exemplo arquetípico de identificadores em linguagens do tipo C [a-zA-Z_][a-zA-Z0-9_]*pode ser lido com um mínimo absoluto de conhecimento de expressões regulares e, uma vez que a barra é atendida, é óbvia e bem sucinta. Exigir menos caracteres não é inerentemente ruim, muito pelo contrário. Ser conciso é uma virtude, desde que você permaneça compreensível.

Há pelo menos duas razões pelas quais essa sintaxe se destaca em padrões simples como estes: ela não requer escape para a maioria dos caracteres, portanto é relativamente natural e usa toda a pontuação disponível para expressar uma variedade de combinadores simples de análise. Talvez o mais importante seja que não requer nada para o seqüenciamento. Você escreve a primeira coisa, depois a que vem depois. Compare isso com o seu followedBy, especialmente quando o padrão a seguir não for uma expressão literal, mas uma expressão mais complicada.

Então, por que eles ficam aquém em casos mais complicados? Eu posso ver três problemas principais:

  1. Não há recursos de abstração. Gramáticas formais, originárias do mesmo campo da ciência da computação teórica que as expressões regulares, têm um conjunto de produções, para que possam dar nomes a partes intermediárias do padrão:

    # This is not equivalent to the regex in the question
    # It's just a mock-up of what a grammar could look like
    url      ::= protocol? '/'? '/'? '/'? (domain_part '.')+ tld
    protocol ::= letter+ ':'
    ...
    
  2. Como vimos acima, o espaço em branco sem significado especial é útil para permitir uma formatação mais fácil aos olhos. A mesma coisa com os comentários. Expressões regulares não podem fazer isso porque um espaço é apenas isso, um literal ' '. Observe, porém: algumas implementações permitem um modo "detalhado" em que espaço em branco é ignorado e comentários são possíveis.

  3. Não há meta-linguagem para descrever padrões e combinadores comuns. Por exemplo, alguém pode escrever uma digitregra uma vez e continuar usando-a em uma gramática livre de contexto, mas não se pode definir uma "função", por assim dizer, que recebe uma produção pe cria uma nova produção que faz algo extra com ela, por exemplo, criar uma produção para uma lista separada por vírgula de ocorrências de p.

A abordagem que você propõe certamente resolve esses problemas. Simplesmente não os resolve muito bem, porque negocia com muito mais concisão do que o necessário. Os dois primeiros problemas podem ser resolvidos, permanecendo em uma linguagem específica de domínio relativamente simples e concisa. A terceira, bem ... uma solução programática requer uma linguagem de programação de propósito geral, é claro, mas, na minha experiência, a terceira é de longe o menor desses problemas. Poucos padrões têm ocorrências suficientes da mesma tarefa complexa que o programador anseia pela capacidade de definir novos combinadores. E quando isso é necessário, o idioma geralmente é complicado o suficiente para que não possa e não deva ser analisado com expressões regulares de qualquer maneira.

Existem soluções para esses casos. Existem aproximadamente dez mil bibliotecas combinadoras de analisador que fazem aproximadamente o que você propõe, apenas com um conjunto diferente de operações, sintaxe muitas vezes diferente e quase sempre com mais poder de análise do que expressões regulares (ou seja, elas lidam com linguagens sem contexto ou com algum tamanho considerável). subconjunto desses). Depois, há geradores de analisador, que seguem a abordagem "use a DSL better" descrita acima. E sempre há a opção de escrever algumas das análises manualmente, em código apropriado. Você pode até misturar e combinar, usando expressões regulares para subtarefas simples e fazendo as coisas complicadas no código que invoca as expressões regulares.

Não sei o suficiente sobre os primeiros anos da computação para explicar como as expressões regulares se tornaram tão populares. Mas eles estão aqui para ficar. Você só precisa usá-los com sabedoria e não usá-los quando isso for mais sábio.


9
I don't know enough about the early years of computing to explain how regular expressions came to be so popular.No entanto, podemos arriscar um palpite: um mecanismo básico de expressão regular é muito fácil de implementar, muito mais fácil do que um analisador eficiente e sem contexto.
biziclop 29/09/2015

15
@ Biziclop Eu não superestimaria essa variável. O Yacc, que aparentemente tinha antecessores suficientes para ser chamado de " mais um compilador", foi criado no início dos anos 70 e foi incluído no Unix uma versão anterior grep(Versão 3 vs Versão 4). Parece que o primeiro grande uso de regex foi em 1968.

Eu só posso seguir o que encontrei na Wikipedia (por isso não acreditaria 100%), mas, de acordo com isso, yaccfoi criada em 1975, toda a idéia dos analisadores LALR (que estavam entre a primeira classe de analisadores praticamente utilizáveis ​​de seus tipo) se originou em 1973. Enquanto a primeira implementação do mecanismo de expressão regular que o JIT compilou expressões (!) foi publicada em 1968. Mas você está certo, é difícil dizer o que mudou, na verdade é difícil dizer quando as expressões regulares começaram a fora". Mas eu suspeito que, uma vez que eles foram colocados nos editores de texto usados ​​pelos desenvolvedores, eles também queriam usá-los em seu próprio software.
precisa saber é o seguinte

1
@ jpmc26 abre seu livro, JavaScript The Good Parts, para o capítulo Regex.
Viziionary

2
with very few differences between dialectsEu não diria que são "muito poucos". Qualquer classe de caracteres predefinida possui várias definições entre diferentes dialetos. E também existem peculiaridades de análise específicas para cada dialeto.
Nhahtdh

39

Perspectiva histórica

O artigo da Wikipedia é bastante detalhado sobre as origens das expressões regulares (Kleene, 1956). A sintaxe original relativamente simples, com apenas *, +, ?, |e agrupamento (...). Era conciso ( e legível, os dois não são necessariamente opostos), porque as linguagens formais tendem a ser expressas com notações matemáticas concisas.

Mais tarde, a sintaxe e os recursos evoluíram com os editores e cresceram com o Perl , que estava tentando ser conciso pelo design ( "construções comuns devem ser curtas" ). Isso complexou bastante a sintaxe, mas observe que as pessoas agora estão acostumadas a expressões regulares e sabem escrever (se não estiverem lendo). O fato de às vezes serem apenas de gravação sugere que, quando são muito longos, geralmente não são a ferramenta certa. Expressões regulares tendem a ser ilegíveis quando são abusadas.

Além das expressões regulares baseadas em string

Falando sobre sintaxes alternativas, vamos dar uma olhada em uma que já existe ( cl-ppcre , em Common Lisp ). Sua expressão regular longa pode ser analisada da ppcre:parse-stringseguinte maneira:

(let ((*print-case* :downcase)
      (*print-right-margin* 50))
  (pprint
   (ppcre:parse-string "^(?:([A-Za-z]+):)?(\\/{0,3})(0-9.\\-A-Za-z]+)(?::(\\d+))?(?:\\/([^?#]*))?(?:\\?([^#]*))?(?:#(.*))?$")))

... e resulta da seguinte forma:

(:sequence :start-anchor
 (:greedy-repetition 0 1
  (:group
   (:sequence
    (:register
     (:greedy-repetition 1 nil
      (:char-class (:range #\A #\Z)
       (:range #\a #\z))))
    #\:)))
 (:register (:greedy-repetition 0 3 #\/))
 (:register
  (:sequence "0-9" :everything "-A-Za-z"
   (:greedy-repetition 1 nil #\])))
 (:greedy-repetition 0 1
  (:group
   (:sequence #\:
    (:register
     (:greedy-repetition 1 nil :digit-class)))))
 (:greedy-repetition 0 1
  (:group
   (:sequence #\/
    (:register
     (:greedy-repetition 0 nil
      (:inverted-char-class #\? #\#))))))
 (:greedy-repetition 0 1
  (:group
   (:sequence #\?
    (:register
     (:greedy-repetition 0 nil
      (:inverted-char-class #\#))))))
 (:greedy-repetition 0 1
  (:group
   (:sequence #\#
    (:register
     (:greedy-repetition 0 nil :everything)))))
 :end-anchor)

Essa sintaxe é mais detalhada e, se você observar os comentários abaixo, não é necessariamente mais legível. Portanto, não presuma que, como você possui uma sintaxe menos compacta, as coisas serão automaticamente mais claras .

No entanto, se você começar a ter problemas com suas expressões regulares, transformá-las nesse formato pode ajudá-lo a decifrar e depurar seu código. Essa é uma vantagem sobre os formatos baseados em cadeias, onde um erro de um único caractere pode ser difícil de detectar. A principal vantagem dessa sintaxe é manipular expressões regulares usando um formato estruturado em vez de uma codificação baseada em string. Isso permite que você componha e construa expressões como qualquer outra estrutura de dados em seu programa. Quando eu uso a sintaxe acima, isso geralmente ocorre porque eu quero construir expressões de partes menores (veja também minha resposta do CodeGolf ). Para seu exemplo, podemos escrever 1 :

`(:sequence
   :start-anchor
   ,(protocol)
   ,(slashes)
   ,(domain)
   ,(top-level-domain) ... )

Expressões regulares baseadas em string também podem ser compostas, usando concatenação e / ou interpolação de string agrupadas em funções auxiliares. No entanto, existem limitações nas manipulações de strings que tendem a confundir o código (pense em problemas de aninhamento, não muito diferentes de backticks vs. $(...)bash; também, caracteres de escape podem causar dores de cabeça).

Observe também que o formulário acima permite (:regex "string")formulários para que você possa misturar notações concisas com árvores. Tudo isso leva o IMHO a boa legibilidade e composição; aborda os três problemas expressos por delnan , indiretamente (ou seja, não na linguagem das expressões regulares).

Concluir

  • Para a maioria dos propósitos, a notação concisa é de fato legível. Existem dificuldades ao lidar com notações estendidas que envolvem retorno, etc., mas raramente são justificadas. O uso injustificado de expressões regulares pode levar a expressões ilegíveis.

  • Expressões regulares não precisam ser codificadas como seqüências de caracteres. Se você tem uma biblioteca ou uma ferramenta que pode ajudá-lo a criar e compor expressões regulares, você evitará muitos bugs em potencial relacionados à manipulação de strings.

  • Alternativamente, as gramáticas formais são mais legíveis e são melhores para nomear e abstrair sub-expressões. Os terminais são geralmente expressos como expressões regulares simples.


1. Você pode preferir criar suas expressões em tempo de leitura, porque expressões regulares tendem a ser constantes em um aplicativo. Veja create-scannere load-time-value:

'(:sequence :start-anchor #.(protocol) #.(slashes) ... )

5
Talvez eu esteja acostumado à sintaxe tradicional do RegEx, mas não tenho tanta certeza de que 22 linhas um tanto legíveis sejam mais fáceis de entender do que o equivalente de uma linha equivalente.

3
@ dan1111 "um pouco legível" ;-) Ok, mas se você precisa ter um tempo muito longo regex, faz sentido definir subconjuntos, como digits, idente compô-los. A maneira como vejo que isso é feito geralmente é com manipulações de cordas (concatenação ou interpolação), o que traz outros problemas, como a fuga adequada. Procure por ocorrências \\\\`nos pacotes emacs, por exemplo. Aliás, esta é agravada porque o mesmo caractere de escape é utilizado tanto para caracteres especiais como \ne \"e para a sintaxe regex \(. Um exemplo não lisp de boa sintaxe é printfonde %dnão entra em conflito \d.
Coredump

1
ponto justo sobre os subconjuntos definidos. Isso faz muito sentido. Estou apenas cético de que a verbosidade é uma melhoria. Pode ser mais fácil para iniciantes (embora conceitos como greedy-repetitionnão sejam intuitivos e ainda precisem ser aprendidos). No entanto, sacrifica a usabilidade para especialistas, pois é muito mais difícil ver e entender todo o padrão.

@ dan1111 Concordo que a verbosidade por si só não é uma melhoria. O que pode ser uma melhoria é manipular regex usando dados estruturados em vez de strings.
Coredump

@ dan1111 Talvez eu deva propor uma edição usando Haskell? Parsec faz isso em apenas nove linhas; como uma linha: do {optional (many1 (letter) >> char ':'); choice (map string ["///","//","/",""]); many1 (oneOf "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-."); optional (char ':' >> many1 digit); optional (char '/' >> many (noneOf "?#")); optional (char '?' >> many (noneOf "#")); optional (char '#' >> many (noneOf "\n")); eof}. Com algumas linhas, como designar a cadeia longa como domainChars = ...e section start p = optional (char start >> many p)parece bem simples.
CR Drost

25

O maior problema do regex não é a sintaxe excessivamente concisa, é que tentamos expressar uma definição complexa em uma única expressão, em vez de compor a partir de blocos de construção menores. Isso é semelhante à programação em que você nunca usa variáveis ​​e funções e, em vez disso, incorpora seu código em uma única linha.

Compare regex com BNF . Sua sintaxe não é muito mais limpa que a expressão regular, mas é usada de maneira diferente. Você começa definindo símbolos nomeados simples e os compõe até chegar a um símbolo que descreve todo o padrão que deseja corresponder.

Por exemplo, observe a sintaxe do URI em rfc3986 :

URI           = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
scheme        = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
hier-part     = "//" authority path-abempty
              / path-absolute
              / path-rootless
              / path-empty
...

Você pode escrever quase a mesma coisa usando uma variante da sintaxe regex que suporta a incorporação de sub-expressões nomeadas.


Pessoalmente, acho que uma regex concisa como sintaxe é adequada para recursos comumente usados, como classes de caracteres, concatenação, escolha ou repetição, mas para recursos mais complexos e raros, como nomes detalhados antecipados, são preferíveis. Muito semelhante à forma como usamos os operadores como +ou *em programação normal e mudar para funções nomeadas para operações mais raros.


12

selfDocumentingMethodName () é muito melhor que e ()

é isso? Há uma razão pela qual a maioria dos idiomas tem {e} como delimitadores de bloco, em vez de BEGIN e END.

As pessoas gostam de concisão e, depois que você conhece a sintaxe, a terminologia curta é melhor. Imagine o seu exemplo de regex, se d (para dígito) for 'dígito', a regex seria ainda mais horrível de se ler. Se você o tornasse mais facilmente analisável com caracteres de controle, seria mais parecido com XML. Nem são tão bons quando você conhece a sintaxe.

No entanto, para responder sua pergunta corretamente, você deve perceber que a regex vem dos dias em que a dispersão era obrigatória. É fácil pensar que um documento XML de 1 MB não é grande coisa hoje, mas estamos falando de dias em que 1 MB era praticamente toda a sua capacidade de armazenamento. Também havia menos idiomas usados ​​naquela época, e o regex não fica a um milhão de milhas de distância de perl ou C, portanto a sintaxe seria familiar para os programadores da época que ficariam felizes em aprender a sintaxe. Portanto, não havia razão para torná-lo mais detalhado.


1
selfDocumentingMethodNameé geralmente aceito como melhor do que eporque a intuição do programador não se alinha à realidade em termos do que realmente constitui legibilidade ou código de boa qualidade . As pessoas que concordam estão erradas, mas é assim que as coisas são.
Leushenko

1
@Leushenko: Você está afirmando que e()é melhor do que selfDocumentingMethodName()?
JacquesB

3
@ JacquesB talvez não em todos os contextos (como um nome global). Mas para coisas com escopo estreito? Quase certamente. Definitivamente mais frequentemente do que diz a sabedoria convencional.
Leushenko

1
@Leushenko: Eu tenho dificuldade em imaginar um contexto onde um nome de função de letra única é melhor do que um nome mais descritivo. Mas acho que isso é pura opinião.
JacquesB

1
@MilesRout: Na verdade, o exemplo é para e()versus um nome de método de auto-documentação . Você pode explicar em que contexto é uma melhoria usar nomes de métodos de letra única em vez de nomes descritivos de métodos?
JacquesB

6

Regex é como peças de lego. À primeira vista, você vê algumas peças de plástico com formas diferentes que podem ser unidas. Você pode pensar que não haveria muitas coisas diferentes possíveis que você pode moldar, mas então você vê as coisas incríveis que outras pessoas fazem e se pergunta como é um brinquedo incrível.

Regex é como peças de lego. Existem poucos argumentos que podem ser usados, mas encadeá-los de formas diferentes formarão milhões de padrões de regex diferentes que podem ser usados ​​para muitas tarefas complicadas.

As pessoas raramente usavam parâmetros regex sozinhos. Muitos idiomas oferecem funções para verificar o comprimento de uma string ou dividir as partes numéricas. Você pode usar funções de seqüência de caracteres para cortar textos e reformá-los. O poder do regex é percebido quando você usa formulários complexos para executar tarefas complexas muito específicas.

Você pode encontrar dezenas de milhares de perguntas sobre expressões regulares no SO e elas raramente são marcadas como duplicadas. Isso por si só mostra os possíveis casos de uso únicos que são muito diferentes um do outro.

E não é fácil oferecer métodos predefinidos para lidar com tarefas muito diferentes. Você possui funções de string para esse tipo de tarefa, mas se essas funções não forem suficientes para sua tarefa especifix, é hora de usar regex


2

Reconheço que este é um problema de prática e não de potência. O problema geralmente surge quando expressões regulares são implementadas diretamente , em vez de assumir uma natureza composta. Da mesma forma, um bom programador decomporá as funções de seu programa em métodos concisos.

Por exemplo, uma sequência de expressões regulares para uma URL pode ser reduzida de aproximadamente:

UriRe = [scheme][hier-part][query][fragment]

para:

UriRe = UriSchemeRe + UriHierRe + "(/?|/" + UriQueryRe + UriFragRe + ")"
UriSchemeRe = [scheme]
UriHierRe = [hier-part]
UriQueryRe = [query]
UriFragRe = [fragment]

Expressões regulares são coisas bacanas, mas tendem a ser abusadas por quem fica absorvido em sua aparente complexidade. As expressões resultantes são retóricas, ausentes de um valor a longo prazo.


2
Infelizmente, a maioria das linguagens de programação não inclui funcionalidades que ajudam na composição de expressões regulares e a maneira como a captura de grupo funciona também não é muito amigável para a composição.
CodesInChaos

1
Outros idiomas precisam alcançar o Perl 5 em seu suporte "expressão regular compatível com perl". Subexpressões não são a mesma coisa que simplesmente concatenar cadeias de caracteres de especificação de regex. As capturas devem ser nomeadas, sem depender de numeração implícita.
JDługosz

0

Como o @cmaster diz, os regexps foram projetados para serem usados ​​apenas em tempo real, e é simplesmente bizarro (e um pouco deprimente) que a sintaxe do ruído da linha ainda seja a mais popular. As únicas explicações em que consigo pensar envolvem inércia, masoquismo ou machismo (não é sempre que 'inércia' é a razão mais atraente para se fazer algo ...)

Perl faz uma tentativa bastante fraca de torná-los mais legíveis, permitindo espaços em branco e comentários, mas não faz nada remotamente imaginativo.

Existem outras sintaxes. Uma boa é a sintaxe scsh para regexps , que na minha experiência produz regexps razoavelmente fáceis de digitar, mas ainda legíveis após o fato.

[ scsh é esplêndido por outros motivos, apenas um dos quais é o famoso texto de agradecimentos ]


2
Perl6 faz! Veja gramáticas.
JDługosz

@ JDługosz Até onde eu sei, isso parece mais um mecanismo para geradores de analisadores, em vez de uma sintaxe alternativa para expressões regulares. Mas a distinção talvez não seja profunda.
Norman Gray

Pode ser um substituto, mas não está limitado ao mesmo poder. Você pode converter um regedp em uma gramática embutida com 1 a 1 correspondência dos modificadores, mas em uma sintaxe mais legível. Exemplos de promovê-lo como tal estão no Perl Apocalypse original.
JDługosz

0

Acredito que expressões regulares foram projetadas para serem o mais geral e simples possível, para que possam ser usadas (aproximadamente) da mesma maneira em qualquer lugar.

Seu exemplo regex.isRange(..).followedBy(..)é acoplado à sintaxe de uma linguagem de programação específica e, talvez, ao estilo orientado a objetos (encadeamento de métodos).

Como esta 'regex' exata ficaria em C, por exemplo? O código teria que ser alterado.

A abordagem mais "geral" seria definir uma linguagem concisa simples que possa ser facilmente incorporada em qualquer outra linguagem sem alterações. E é isso (quase) o que é regex.


0

Os mecanismos de expressão regular compatível com Perl são amplamente utilizados, fornecendo uma sintaxe concisa de expressão regular que muitos editores e idiomas entendem. Como @ JDługosz apontou nos comentários, o Perl 6 (não apenas uma nova versão do Perl 5, mas uma linguagem totalmente diferente) tentou tornar as expressões regulares mais legíveis, construindo-as a partir de elementos definidos individualmente. Por exemplo, aqui está um exemplo de gramática para analisar URLs do Wikibooks :

grammar URL {
  rule TOP {
    <protocol>'://'<address>
  }
  token protocol {
    'http'|'https'|'ftp'|'file'
  }
  rule address {
    <subdomain>'.'<domain>'.'<tld>
  }
  ...
}

Dividir a expressão regular como essa permite que cada bit seja definido individualmente (por exemplo, restrição domaina ser alfanumérica) ou estendido por subclassificação (por exemplo, FileURL is URLque restrições protocolsejam apenas "file").

Portanto: não, não há razão técnica para a dispersão das expressões regulares, mas as formas mais novas, mais limpas e mais legíveis de representá-las já estão aqui! Portanto, esperamos ver novas idéias nesse campo.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.