Estou lendo Design de Software para Flexibilidade (SDF) . O Exercício 2.10 pede para implementar o tradutor tanto para BRE quanto para ERE. O livro usa grep
para testar a string traduzida como (a.c)
em ERE para capturar algo como abc
ou adc
.
Eu uso Arch Linux.
Pela especificação POSIX 9.3.3 BRE Special Characters, \+
não é suportado pelo BRE.
Mas man grep
"Expressões Regulares Básicas vs Estendidas" permite \+
a opção padrão BRE .
A diferença acima parece estar implícita neste problema de especificações (referência deste controle de qualidade ):
O BRE corresponde ao tipo ed ou grep histórico
Mas ed
parece também apoiar\+
.
(Editado: este parágrafo está errado, pois este site não está em conformidade com o BRE quando a opção b está habilitada. (ab)
Em vez de \(ab\)
corresponderá a "ab".) https://www.regexplanet.com/advanced/postgresql/index.html pode suportar o mero BRE, mas é um pouco lento e não pode ser facilmente incorporado ao código do Scheme (estou aprendendo SICP e SDF, então não verifiquei a implementação do Http no Scheme. O livro acima usa shell para executargrep
). Eu uso expressão a\+c
e entrada abc
para testar com a opção b habilitada. Mostra "regex_matches()" sendo "(nenhum)".
Então existe uma ferramenta regex seguindo exatamente o BRE?
POSIX define alguns caracteres, conhecidos como metacaracteres ou "caracteres especiais", que possuem significados não literais quando usados em uma regexp, por exemplo,
.
corresponde a qualquer caractere. POSIX também define o que acontece quando você coloca uma barra invertida\
antes de tal metacaractere, ou seja, ela se torna literal e corresponde a um caractere\.
literal ..
Caracteres que não são tais metachares, por exemplo
s
(ou+
em um BRE), são conhecidos como "caracteres comuns". O que o POSIX diz sobre caracteres comuns é o seguinte (ênfase minha):ou seja, NÃO define especificamente o que acontece quando você coloca um
\
na frente de um caractere comum (exceto os poucos mencionados acima), e é por isso que as ferramentas podem definir\s
o mesmo significado[[:space:]]
daquela ferramenta e ainda estar em conformidade com o padrão POSIX, já que qualquer ferramenta pode faça o que quiser com a entrada, de forma que o POSIX não defina como lidar com essa entrada.A respeito de:
A maioria (todas?)
grep
Esed
as implementações o fazem por padrão, mas uma ferramenta que implementa SOMENTE os comportamentos definidos pelo POSIX, como eu acho que você espera, simplesmente não pode existir porque o POSIX deliberadamente não define tudo (o POSIX descreve a funcionalidade comum que a maioria das ferramentas tem na maioria das situações, não dita como todas as ferramentas devem se comportar em todas as situações) e, portanto, quem está implementando qualquer versão de qualquer ferramenta tem que tomar sua própria decisão sobre o que fazer quando essa ferramenta encontrar alguma entrada cujo manuseio é não definido pelo POSIX - implemente algumas funcionalidades que eles acham que serão úteis, trate-as como caracteres literais, imprima uma mensagem de aviso, apague todos os seus arquivos, corrompa seu disco rígido ou qualquer outra coisa que acharem adequada. Contanto que implementem a funcionalidade definida pelo POSIX, essa ferramenta será compatível com POSIX, independentemente do que faça nos casos indefinidos.Considere que existe um padrão para carros que diz “quando o motorista vira o volante para a direita, o carro vira para a direita”. Espera-se que um fabricante de automóveis cumpra esse requisito. O padrão provavelmente não define o que acontece se você puxar o volante em sua direção, então se a Nissan decidir que se você fizer isso em um Maxima 2015, o carro decolará e começará a voar ou se comprimirá em um pequeno cubo, isso ainda é compatível com o padrão. Da mesma forma, o POSIX define o que
.
,s
e\.
significa, mas o POSIX não define o que\s
significa e, portanto, o GNU pode definir\s
como equivalente[[:space:]]
ou o que quiser e ainda ser compatível com POSIX.Portanto, se você deseja um regexp que se comporte da mesma forma em todas as versões de uma ferramenta, como
grep
nas formas definidas pelo POSIX, apenas não escreva um regexp que dependa de um comportamento indefinido pelo POSIX. Isso inclui não escrever\+
em BRE e não escrever\s
em BRE ou ERE, e tudo o quegrep
você estiver usando estará em conformidade com o padrão POSIX aplicável ao processar esse regexp.Regexps POSIX, BREs e EREs, são definidos no padrão POSIX , não na página de manual de qualquer ferramenta e definitivamente não em regex101.com, onde AFAIK não tem uma opção para lidar com BREs ou EREs POSIX.
Em relação à sugestão nos comentários para definir
POSIXLY_CORRECT
:POSIXLY_CORRECT
aplica-se apenas a ferramentas GNU, portanto não ajudaria com ferramentas BSD, etc., e o que faz varia de acordo com cada ferramenta, mesmo dentro do GNU, por exemplo, no GNU awk com POSIXLY_CORRECT defina-o reportará\s
como comportamento indefinido e o tratará apenas como um literals
em um regexp, enquanto no GNU grep tratará\s
(e\+
) da mesma maneira, esteja POSIXLY_CORRECT definido ou não. Por exemplo: