Usando o FreeBSD 11.1:
#!/bin/sh
if printf 'abcde.fgh' | grep -iEq '^[^][$^*_-]'; then
echo "test 1 success"
else
echo "test 1 fail"
fi
echo
if printf 'abcde.fgh' | grep -iEq '^[^][.$^*_-]'; then
echo "test 2 success"
else
echo "test 2 fail"
fi
Saída:
test 1 success
grep: Unmatched [ or [^
test 2 fail
Mas AFAICT estes devem dar o mesmo resultado. Ambos contêm uma condição no primeiro caractere (apenas), de que não faz parte de uma lista de caracteres não alfabéticos especificados. Detalhamento do regex:
^
= início da string[^...]
= corresponde se nenhum desses caracteres- Dentro da lista,
]
deve ser o primeiro caractere,^
não deve ser o primeiro e - deve ser o último. Portanto,][.^$_-
é uma lista válida de caracteres literais e a string não deve corresponder a nenhum deles. - Para evitar confusão, observe que isso significa que
][
são literais"]"
e"["
caracteres na lista,nãoum fechamento e reabertura de 2 listas.
A única diferença entre as 2 expressões é que "."
está dentro de uma lista, portanto deve ser tratada como not literal .
e de fato o primeiro caractere não corresponde ao literal"."
o que estou perdendo? Algo muito óbvio e simples, provavelmente?
Responder1
Estão faltando algumas outras regras de sintaxe. Dentro de uma expansão de colchetes, além dos intervalos simples, também existem alguns tipos de expressões com vários caracteres que começam com [
. (Veja oexpressão regular(7)manual paraLinuxouFreeBSDem "Com exceção destese algumas combinações usando '['(veja os próximos parágrafos)".) São eles:
- Elementos de agrupamento:
[.
….]
- Classes de equivalência:
[=
…=]
- Classes de personagens:
[:
…:]
(Você pode ter visto ou usado expressões como [[:digit:]]
– estas são na verdade uma classe de caracteres [:digit:]
que é o único elemento de uma […]
expansão de colchetes.)
Portanto, no seu caso, como .
acontece imediatamente após a [
, eles são reconhecidos como o delimitador de abertura de um elemento de agrupamento. GNU grep 3.1 tem a mensagem de erro correta:
$ printf 'abcde.fgh' | grep -iEq '^[^][.$^*_-]'
grep: Unmatched [, [^, [:, [., or [=
As mesmas expressões podem ser usadas para escapar de tais situações usando, por exemplo, [...]
ou [=.=]
para incluir um ponto regular, ou similarmente [=-=]
para corresponder a um traço, se não houver para onde movê-los.