Depois de executar
grep '[a-z]\{22\}' /usr/share/dict/words
a saída é
counterrevolutionaries
electroencephalographs
mas durante a execução
grep '[^a-z]\{22\}' /usr/share/dict/words
não há saída.
Eu esperava que ele gerasse resultados semelhantes aos de
grep -v '[a-z]\{22\}' /usr/share/dict/words
Minha pergunta é o que há de errado e por quê?
[specification]
corresponde a um elemento de agrupamento (pode ser um caractere ou sequência de caracteres conforme definido no algoritmo de agrupamento para a localidade (por exemplo, em localidades húngaras em sistemas GNU,dzs
é um elemento de agrupamento que classifica em algum lugar entred
ee
)) no conjunto especificado .Essa especificação pode incluir
a-z
(ou[.dzs.]-z
) para agrupar elementos agrupados entrea
ez
(observe que geralmente inclui abcdefghijklmnoprstuvwxyz, mas na maioria dos locais, inclui muito mais). Além disso, como o POSIX deixa sem especificação para localidades diferentes das localidades POSIX, o quanto esses intervalos são baseados na ordem de agrupamento varia significativamente entre as implementações.x
,[.dsz.]
)[:alpha:]
,[:digit:]
[=e=]
para todos os elementos de agrupamento que têm o mesmo peso de agrupamento primário quee
(pode incluir coisas comoé
)Portanto, por exemplo,
[acd[=e=]h-k[:digit:][.dzs.]]
corresponde a um elemento de agrupamento, desde que sejaa
,c
,d
,dzs
ou seja equivalente ae
ou agrupe entreh
ek
ou seja classificado como dígito .E se a especificação começar com
^
, ainda corresponderá a um elemento de agrupamento, mas com o conjunto complementado. Isso é qualquer elemento de agrupamento, exceto os especificados.Portanto
[^a-z]
, corresponde a qualquer elemento de agrupamento que não seja agrupado entrea
ez
. Por exemplo, provavelmente corresponderia a1
eẑ
, possivelmente aX
ouDSZ
dependendo da localidade e dagrep
implementação, mas não aa
,x
nemz
e provavelmente não aé
.So
grep '[^a-z]\{22\}'
corresponde em linhas que contêm uma sequência de22
elementos de agrupamento que agrupam antesa
ou depoisz
.Enquanto
grep -v '[a-z]\{22\}'
corresponde a linhas que não contêm uma sequência de 22 elementos de agrupamento agrupados entrea
ez
.Combinar o mesmo sem
-v
é quase impossível de implementar, você precisa combinar em linhas que não contenham mais de 21[a-z]
elementos de agrupamento entre dois[^a-z]
elementos. Mas se a localidade oferecer suporte a elementos de agrupamento de vários caracteres, isso não será realmente possível. Por exemplo, nessas localidades húngaras,[a-z]
corresponde adsz
mas também ad
,s
, ez
você descobrirá que ali,[a-z]{0,21}
corresponderá adszxxxyyyxxxyyyxxxyyyx
mas também corresponderia[a-z]{22}
.Para localidades que não possuem elementos de agrupamento de vários caracteres, você pode fazer algo como:
Agora, também existem algumas
grep
implementações que suportam sintaxes regulares mais avançadas com opções que possuem algum operador de negação .Por exemplo, a implementação GNU ou ast-open de
grep
suporte perl-like (usando libpcre no GNU grep, a própria implementação do ast-open para ast-open grep) expressões regulares com a-P
opção que tem um(?!pattern)
operador de antecipação negativo .(?!pattern)
corresponde a largura zero em qualquer ponto da string de assunto, desde que o padrão não corresponda a partir daí. Então alguém poderia usar:para corresponder ao início da linha, desde que não seja seguido por nenhum número de caracteres e 22
[a-z]
s. Observe, no entanto, que em PCRE (não em ast-open),[a-z]
apenas correspondências em abcdefghijklmnopqrstuvwxyz, independentemente da localidade.ast-open também tem uma
-X
opção para o que eles chamam de regexps aumentados . Esses regex aumentados têm um!
operador que nega as coisas.x!
corresponderia a qualquer coisa diferente dex
(incluindo a string vazia).Assim, com ast-open
grep
, você também pode fazer:grep '[^a-z]\{22\}' /usr/share/dict/words
Procura linhas no arquivo
/usr/share/dict/words
que contenham uma string de 22 caracteres que não sejam letras minúsculas. É muito provável que o arquivo não contenha tal linha. (Por que esse arquivo conteria strings de 22 não-letras?)grep -v '[a-z]\{22\}' /usr/share/dict/words
Procura por linhas que não contenham strings de 22 letras. Provavelmente haverá muitas dessas linhas. (Porque a maioria das palavras tem menos de 22 letras.)